blob: 38f1e0387fb714736db41080339389f9daf57321 [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
20#include <sstream>
21#include <string>
22#include <vector>
23
24#include <cutils/log.h>
25
26#define EGL_EGLEXT_PROTOTYPES
27#define GL_GLEXT_PROTOTYPES
28
29#include <EGL/egl.h>
30#include <EGL/eglext.h>
31#include <GLES2/gl2.h>
32#include <GLES2/gl2ext.h>
33
34#include <hardware/hardware.h>
35#include <hardware/hwcomposer.h>
36
37#include <ui/GraphicBuffer.h>
38#include <ui/PixelFormat.h>
Stéphane Marchesinbe98c8c2015-06-23 16:18:10 -070039#include <utils/Trace.h>
Zach Reizner01935f32015-04-29 11:15:09 -070040
41#include <cutils/properties.h>
42#include <sync/sync.h>
43#include <sw_sync.h>
44
45#include "drm_hwcomposer.h"
46
47#include "gl_compositor.h"
48#include "seperate_rects.h"
49
50// TODO(zachr): use hwc_drm_bo to turn buffer handles into textures
51#ifndef EGL_NATIVE_HANDLE_ANDROID_NVX
52#define EGL_NATIVE_HANDLE_ANDROID_NVX 0x322A
53#endif
54
55#define MAX_OVERLAPPING_LAYERS 64
56
57namespace android {
58
59struct GLCompositor::texture_from_handle {
60 EGLImageKHR image;
61 GLuint texture;
62};
63
64static const char *get_gl_error(void);
65static const char *get_egl_error(void);
66static bool has_extension(const char *extension, const char *extensions);
67
68template <typename T>
69int AllocResource(std::vector<T> &array) {
70 for (typename std::vector<T>::iterator it = array.begin(); it != array.end();
71 ++it) {
72 if (!it->is_some()) {
73 return std::distance(array.begin(), it);
74 }
75 }
76
77 array.push_back(T());
78 return array.size() - 1;
79}
80
81template <typename T>
82void FreeResource(std::vector<T> &array, int index) {
83 if (index == (int)array.size() - 1) {
84 array.pop_back();
85 } else if (index >= 0 && (unsigned)index < array.size()) {
86 array[index].Reset();
87 }
88}
89
90struct GLTarget {
91 sp<GraphicBuffer> fb;
92 EGLImageKHR egl_fb_image;
93 GLuint gl_fb;
94 GLuint gl_fb_tex;
95 bool forgotten;
96 unsigned composition_count;
97
98 GLTarget()
99 : egl_fb_image(EGL_NO_IMAGE_KHR),
100 gl_fb(0),
101 gl_fb_tex(0),
102 forgotten(true),
103 composition_count(0) {
104 }
105
106 void Reset() {
107 fb.clear();
108 egl_fb_image = EGL_NO_IMAGE_KHR;
109 gl_fb = 0;
110 gl_fb_tex = 0;
111 forgotten = true;
112 composition_count = 0;
113 }
114
115 bool is_some() const {
116 return egl_fb_image != EGL_NO_IMAGE_KHR;
117 }
118};
119
120struct GLCompositor::priv_data {
121 EGLDisplay egl_display;
122 EGLContext egl_ctx;
123
124 EGLDisplay saved_egl_display;
125 EGLContext saved_egl_ctx;
126 EGLSurface saved_egl_read;
127 EGLSurface saved_egl_draw;
128
129 int current_target;
130 std::vector<GLTarget> targets;
131 std::vector<GLComposition *> compositions;
132
133 std::vector<GLint> blend_programs;
134 GLuint vertex_buffer;
135
136 priv_data()
137 : egl_display(EGL_NO_DISPLAY),
138 egl_ctx(EGL_NO_CONTEXT),
139 saved_egl_display(EGL_NO_DISPLAY),
140 saved_egl_ctx(EGL_NO_CONTEXT),
141 saved_egl_read(EGL_NO_SURFACE),
142 saved_egl_draw(EGL_NO_SURFACE),
143 current_target(-1) {
144 }
145};
146
147class GLComposition : public Composition {
148 public:
149 struct LayerData {
150 hwc_layer_1 layer;
151 hwc_drm_bo bo;
152 };
153
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700154 GLComposition(GLCompositor *owner, Importer *imp)
155 : compositor(owner), importer(imp), target_handle(-1) {
Zach Reizner01935f32015-04-29 11:15:09 -0700156 }
157
158 virtual ~GLComposition() {
159 if (compositor == NULL) {
160 return;
161 }
162
163 // Removes this composition from the owning compositor automatically.
164 std::vector<GLComposition *> &compositions =
165 compositor->priv_->compositions;
166 std::vector<GLComposition *>::iterator it =
167 std::find(compositions.begin(), compositions.end(), this);
168 if (it != compositions.end()) {
169 compositions.erase(it);
170 }
171
172 GLTarget *target = &compositor->priv_->targets[target_handle];
173 target->composition_count--;
174 compositor->CheckAndDestroyTarget(target_handle);
175 }
176
177 virtual int AddLayer(int display, hwc_layer_1 *layer, hwc_drm_bo *bo) {
178 (void)display;
179 if (layer->compositionType != HWC_OVERLAY) {
180 ALOGE("Must add layers with compositionType == HWC_OVERLAY");
181 return 1;
182 }
183
184 if (layer->handle == 0) {
185 ALOGE("Must add layers with valid buffer handle");
186 return 1;
187 }
188
189 layer_data.push_back(LayerData());
190 LayerData &layer_datum = layer_data.back();
191 layer_datum.layer = *layer;
192 layer_datum.bo = *bo;
193
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700194 return importer->ReleaseBuffer(bo);
Zach Reizner01935f32015-04-29 11:15:09 -0700195 }
196
197 virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const {
198 (void)display;
199 return num_needed;
200 }
201
202 GLCompositor *compositor;
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700203 Importer *importer;
Zach Reizner01935f32015-04-29 11:15:09 -0700204 int target_handle;
205 std::vector<LayerData> layer_data;
206};
207
208struct RenderingCommand {
209 struct TextureSource {
210 unsigned texture_index;
211 float crop_bounds[4];
212 float alpha;
213 };
214
215 float bounds[4];
216 unsigned texture_count;
217 TextureSource textures[MAX_OVERLAPPING_LAYERS];
218
219 RenderingCommand() : texture_count(0) {
220 }
221};
222
223static void ConstructCommands(const GLComposition &composition,
224 std::vector<RenderingCommand> *commands) {
225 std::vector<seperate_rects::Rect<float> > in_rects;
226 std::vector<seperate_rects::RectSet<uint64_t, float> > out_rects;
227 int i;
228
229 for (unsigned rect_index = 0; rect_index < composition.layer_data.size();
230 rect_index++) {
231 const struct hwc_layer_1 &layer = composition.layer_data[rect_index].layer;
232 seperate_rects::Rect<float> rect;
233 in_rects.push_back(seperate_rects::Rect<float>(
234 layer.displayFrame.left, layer.displayFrame.top,
235 layer.displayFrame.right, layer.displayFrame.bottom));
236 }
237
238 seperate_frects_64(in_rects, &out_rects);
239
240 for (unsigned rect_index = 0; rect_index < out_rects.size(); rect_index++) {
241 const seperate_rects::RectSet<uint64_t, float> &out_rect =
242 out_rects[rect_index];
243 commands->push_back(RenderingCommand());
244 RenderingCommand &cmd = commands->back();
245
246 memcpy(cmd.bounds, out_rect.rect.bounds, sizeof(cmd.bounds));
247
248 uint64_t tex_set = out_rect.id_set.getBits();
249 for (unsigned i = composition.layer_data.size() - 1; tex_set != 0x0; i--) {
250 if (tex_set & (0x1 << i)) {
251 tex_set &= ~(0x1 << i);
252
253 const struct hwc_layer_1 &layer = composition.layer_data[i].layer;
254
255 seperate_rects::Rect<float> display_rect(
256 layer.displayFrame.left, layer.displayFrame.top,
257 layer.displayFrame.right, layer.displayFrame.bottom);
258 float display_size[2] = {
259 display_rect.bounds[2] - display_rect.bounds[0],
260 display_rect.bounds[3] - display_rect.bounds[1]};
261
262 seperate_rects::Rect<float> crop_rect(
263 layer.sourceCropf.left, layer.sourceCropf.top,
264 layer.sourceCropf.right, layer.sourceCropf.bottom);
265 float crop_size[2] = {crop_rect.bounds[2] - crop_rect.bounds[0],
266 crop_rect.bounds[3] - crop_rect.bounds[1]};
267
268 RenderingCommand::TextureSource &src = cmd.textures[cmd.texture_count];
269 cmd.texture_count++;
270 src.texture_index = i;
271
272 for (int b = 0; b < 4; b++) {
273 float bound_percent = (cmd.bounds[b] - display_rect.bounds[b % 2]) /
274 display_size[b % 2];
275 src.crop_bounds[b] =
276 crop_rect.bounds[b % 2] + bound_percent * crop_size[b % 2];
277 }
278
279 if (layer.blending == HWC_BLENDING_NONE) {
280 src.alpha = 1.0f;
281 // This layer is opaque. There is no point in using layers below this
282 // one.
283 break;
284 }
285
286 src.alpha = layer.planeAlpha / 255.0f;
287 }
288 }
289 }
290}
291
292GLCompositor::GLCompositor() {
293 priv_ = new priv_data;
294}
295
296GLCompositor::~GLCompositor() {
297 if (BeginContext()) {
298 goto destroy_ctx;
299 }
300
301 glBindFramebuffer(GL_FRAMEBUFFER, 0);
302 glBindTexture(GL_TEXTURE_2D, 0);
303
304 for (std::vector<GLTarget>::iterator it = priv_->targets.end();
305 it != priv_->targets.begin(); it = priv_->targets.end()) {
306 --it;
307 glDeleteFramebuffers(1, &it->gl_fb);
308 glDeleteTextures(1, &it->gl_fb_tex);
309 eglDestroyImageKHR(priv_->egl_display, it->egl_fb_image);
310 priv_->targets.erase(it);
311 }
312
313 for (std::vector<GLComposition *>::iterator it = priv_->compositions.end();
314 it != priv_->compositions.begin(); it = priv_->compositions.end()) {
315 --it;
316
317 // Prevents compositor from trying to erase itself
318 (*it)->compositor = NULL;
319 delete *it;
320 priv_->compositions.erase(it);
321 }
322
323destroy_ctx:
324 eglMakeCurrent(priv_->egl_display,
325 EGL_NO_SURFACE /* No default draw surface */,
326 EGL_NO_SURFACE /* No default draw read */, EGL_NO_CONTEXT);
327 eglDestroyContext(priv_->egl_display, priv_->egl_ctx);
328
329 EndContext();
330 delete priv_;
331}
332
333int GLCompositor::Init() {
334 int ret = 0;
335 const char *egl_extensions;
336 const char *gl_extensions;
337 EGLint num_configs;
338 EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
339 EGLConfig egl_config;
340
341 // clang-format off
342 const GLfloat verts[] = {
343 0.0f, 0.0f, 0.0f, 0.0f,
344 0.0f, 1.0f, 0.0f, 1.0f,
345 1.0f, 0.0f, 1.0f, 0.0f,
346 1.0f, 1.0f, 1.0f, 1.0f
347 };
348 // clang-format on
349
Zach Reizner21b57e82015-06-11 11:40:18 -0700350 const EGLint config_attribs[] = {EGL_RENDERABLE_TYPE,
351 EGL_OPENGL_ES2_BIT,
352 EGL_RED_SIZE,
353 8,
354 EGL_GREEN_SIZE,
355 8,
356 EGL_BLUE_SIZE,
357 8,
358 EGL_NONE};
Zach Reizner01935f32015-04-29 11:15:09 -0700359
360 const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
361
362 priv_->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
363 if (priv_->egl_display == EGL_NO_DISPLAY) {
364 ALOGE("Failed to get egl display");
365 ret = 1;
366 goto out;
367 }
368
369 if (!eglInitialize(priv_->egl_display, NULL, NULL)) {
370 ALOGE("Failed to initialize egl: %s", get_egl_error());
371 ret = 1;
372 goto out;
373 }
374
375 egl_extensions = eglQueryString(priv_->egl_display, EGL_EXTENSIONS);
376
377 // These extensions are all technically required but not always reported due
378 // to meta EGL filtering them out.
379 if (!has_extension("EGL_KHR_image_base", egl_extensions))
380 ALOGW("EGL_KHR_image_base extension not supported");
381
382 if (!has_extension("EGL_ANDROID_image_native_buffer", egl_extensions))
383 ALOGW("EGL_ANDROID_image_native_buffer extension not supported");
384
385 if (!has_extension("EGL_ANDROID_native_fence_sync", egl_extensions))
386 ALOGW("EGL_ANDROID_native_fence_sync extension not supported");
387
388 if (!eglChooseConfig(priv_->egl_display, config_attribs, &egl_config, 1,
389 &num_configs)) {
390 ALOGE("eglChooseConfig() failed with error: %s", get_egl_error());
391 goto out;
392 }
393
394 priv_->egl_ctx =
395 eglCreateContext(priv_->egl_display, egl_config,
396 EGL_NO_CONTEXT /* No shared context */, context_attribs);
397
398 if (priv_->egl_ctx == EGL_NO_CONTEXT) {
399 ALOGE("Failed to create OpenGL ES Context: %s", get_egl_error());
400 ret = 1;
401 goto out;
402 }
403
404 ret = BeginContext();
405 if (ret)
406 goto out;
407
408 gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
409
410 if (!has_extension("GL_OES_EGL_image", gl_extensions))
411 ALOGW("GL_OES_EGL_image extension not supported");
412
413 glGenBuffers(1, &priv_->vertex_buffer);
414 glBindBuffer(GL_ARRAY_BUFFER, priv_->vertex_buffer);
415 glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
416 glBindBuffer(GL_ARRAY_BUFFER, 0);
417
418 if (GenerateShaders()) {
419 ret = 1;
420 goto end_ctx;
421 }
422
423end_ctx:
424 EndContext();
425
426out:
427 return ret;
428}
429
430Targeting *GLCompositor::targeting() {
431 return (Targeting *)this;
432}
433
434int GLCompositor::CreateTarget(sp<GraphicBuffer> &buffer) {
435 int ret;
436
437 ret = BeginContext();
438 if (ret)
439 return -1;
440
441 int target_handle = AllocResource(priv_->targets);
442 GLTarget *target = &priv_->targets[target_handle];
443
444 target->fb = buffer;
445
446 target->egl_fb_image = eglCreateImageKHR(
447 priv_->egl_display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
448 (EGLClientBuffer)target->fb->getNativeBuffer(), NULL /* no attribs */);
449
450 if (target->egl_fb_image == EGL_NO_IMAGE_KHR) {
451 ALOGE("Failed to make image from target buffer: %s", get_egl_error());
452 ret = -1;
453 goto fail_create_image;
454 }
455
456 glGenTextures(1, &target->gl_fb_tex);
457 glBindTexture(GL_TEXTURE_2D, target->gl_fb_tex);
458 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
459 (GLeglImageOES)target->egl_fb_image);
460 glBindTexture(GL_TEXTURE_2D, 0);
461
462 glGenFramebuffers(1, &target->gl_fb);
463 glBindFramebuffer(GL_FRAMEBUFFER, target->gl_fb);
464 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
465 target->gl_fb_tex, 0);
466
467 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
468 ALOGE("Failed framebuffer check for created target buffer");
469 ret = 1;
470 goto fail_framebuffer_status;
471 }
472
473 target->forgotten = false;
474
475 ret = target_handle;
476 goto out;
477
478fail_framebuffer_status:
479 glBindFramebuffer(GL_FRAMEBUFFER, 0);
480 glDeleteFramebuffers(1, &target->gl_fb);
481 glDeleteTextures(1, &target->gl_fb_tex);
482 eglDestroyImageKHR(priv_->egl_display, target->egl_fb_image);
483 target->gl_fb = 0;
484 target->gl_fb_tex = 0;
485 target->egl_fb_image = EGL_NO_IMAGE_KHR;
486
487fail_create_image:
488 target->fb.clear();
489 FreeResource(priv_->targets, target_handle);
490
491out:
492 EndContext();
493 return ret;
494}
495
496void GLCompositor::SetTarget(int target_handle) {
497 if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) {
498 GLTarget *target = &priv_->targets[target_handle];
499 if (target->is_some()) {
500 priv_->current_target = target_handle;
501 return;
502 }
503 }
504
505 priv_->current_target = -1;
506}
507
508void GLCompositor::ForgetTarget(int target_handle) {
509 if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) {
510 if (target_handle == priv_->current_target) {
511 priv_->current_target = -1;
512 }
513
514 GLTarget *target = &priv_->targets[target_handle];
515 if (target->is_some()) {
516 target->forgotten = true;
517 CheckAndDestroyTarget(target_handle);
518 return;
519 }
520 }
521
522 ALOGE("Failed to forget target because of invalid handle");
523}
524
525void GLCompositor::CheckAndDestroyTarget(int target_handle) {
526 GLTarget *target = &priv_->targets[target_handle];
527 if (target->composition_count == 0 && target->forgotten) {
528 if (BeginContext() == 0) {
529 glDeleteFramebuffers(1, &target->gl_fb);
530 glDeleteTextures(1, &target->gl_fb_tex);
531 eglDestroyImageKHR(priv_->egl_display, target->egl_fb_image);
532 EndContext();
533 }
534
535 FreeResource(priv_->targets, target_handle);
536 }
537}
538
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700539Composition *GLCompositor::CreateComposition(Importer *importer) {
Zach Reizner01935f32015-04-29 11:15:09 -0700540 if (priv_->current_target >= 0 &&
541 (unsigned)priv_->current_target < priv_->targets.size()) {
542 GLTarget *target = &priv_->targets[priv_->current_target];
543 if (target->is_some()) {
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700544 GLComposition *composition = new GLComposition(this, importer);
Zach Reizner01935f32015-04-29 11:15:09 -0700545 composition->target_handle = priv_->current_target;
546 target->composition_count++;
547 priv_->compositions.push_back(composition);
548 return composition;
549 }
550 }
551
552 ALOGE("Failed to create composition because of invalid target handle %d",
553 priv_->current_target);
554
555 return NULL;
556}
557
558int GLCompositor::QueueComposition(Composition *composition) {
559 if (composition) {
560 int ret = DoComposition(*(GLComposition *)composition);
561 delete composition;
562 return ret;
563 }
564
565 ALOGE("Failed to queue composition because of invalid composition handle");
566
567 return -EINVAL;
568}
569
570int GLCompositor::Composite() {
571 return 0;
572}
573
574int GLCompositor::BeginContext() {
575 priv_->saved_egl_display = eglGetCurrentDisplay();
576 priv_->saved_egl_ctx = eglGetCurrentContext();
577
578 if (priv_->saved_egl_display != priv_->egl_display ||
579 priv_->saved_egl_ctx != priv_->egl_ctx) {
580 priv_->saved_egl_read = eglGetCurrentSurface(EGL_READ);
581 priv_->saved_egl_draw = eglGetCurrentSurface(EGL_DRAW);
582 } else {
583 return 0;
584 }
585
586 if (!eglMakeCurrent(priv_->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
587 priv_->egl_ctx)) {
588 ALOGE("Failed to make the OpenGL ES Context current: %s", get_egl_error());
589 return 1;
590 }
591 return 0;
592}
593
594int GLCompositor::EndContext() {
595 if (priv_->saved_egl_display != eglGetCurrentDisplay() ||
596 priv_->saved_egl_ctx != eglGetCurrentContext()) {
597 if (!eglMakeCurrent(priv_->saved_egl_display, priv_->saved_egl_read,
598 priv_->saved_egl_draw, priv_->saved_egl_ctx)) {
Zach Reizner21b57e82015-06-11 11:40:18 -0700599 ALOGE("Failed to make the old OpenGL ES Context current: %s",
Zach Reizner01935f32015-04-29 11:15:09 -0700600 get_egl_error());
601 return 1;
602 }
603 }
604
605 return 0;
606}
607
608GLint CompileAndCheckShader(GLenum type, unsigned source_count,
609 const GLchar **sources, std::string *shader_log) {
610 GLint status;
611 GLint shader = glCreateShader(type);
612 if (!shader) {
613 *shader_log = "glCreateShader failed";
614 return 0;
615 }
616 glShaderSource(shader, source_count, sources, NULL);
617 glCompileShader(shader);
618 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
619 if (!status) {
620 if (shader_log) {
621 GLint log_length;
622 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
623 shader_log->resize(log_length);
624 glGetShaderInfoLog(shader, log_length, NULL, &(*shader_log)[0]);
625 }
626 glDeleteShader(shader);
627 return 0;
628 }
629
630 return shader;
631}
632
633int GLCompositor::GenerateShaders() {
634 // Limits: GL_MAX_VARYING_COMPONENTS, GL_MAX_TEXTURE_IMAGE_UNITS,
635 // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
636 // clang-format off
637 const GLchar *shader_preamble = "#version 300 es\n#define LAYER_COUNT ";
638
639 const GLchar *vertex_shader_source =
640"\n"
641"precision mediump int; \n"
642"uniform vec4 uViewport; \n"
643"uniform sampler2D uLayerTextures[LAYER_COUNT]; \n"
644"uniform vec4 uLayerCrop[LAYER_COUNT]; \n"
645"in vec2 vPosition; \n"
646"in vec2 vTexCoords; \n"
647"out vec2 fTexCoords[LAYER_COUNT]; \n"
648"void main() { \n"
649" for (int i = 0; i < LAYER_COUNT; i++) { \n"
650" fTexCoords[i] = (uLayerCrop[i].xy + vTexCoords * uLayerCrop[i].zw) / \n"
651" vec2(textureSize(uLayerTextures[i], 0)); \n"
652" } \n"
653" vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw; \n"
654" gl_Position = vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0); \n"
655"} \n";
656
657 const GLchar *fragment_shader_source =
658"\n"
659"precision mediump float; \n"
660"uniform sampler2D uLayerTextures[LAYER_COUNT]; \n"
661"uniform float uLayerAlpha[LAYER_COUNT]; \n"
662"in vec2 fTexCoords[LAYER_COUNT]; \n"
663"out vec4 oFragColor; \n"
664"void main() { \n"
665" vec3 color = vec3(0.0, 0.0, 0.0); \n"
666" float alphaCover = 1.0; \n"
667" for (int i = 0; i < LAYER_COUNT; i++) { \n"
668" vec4 texSample = texture(uLayerTextures[i], fTexCoords[i]); \n"
669" float a = texSample.a * uLayerAlpha[i]; \n"
670" color += a * alphaCover * texSample.rgb; \n"
671" alphaCover *= 1.0 - a; \n"
672" if (alphaCover <= 0.5/255.0) \n"
673" break; \n"
674" } \n"
Zach Reiznerdb556112015-06-11 11:30:20 -0700675" oFragColor = vec4(color, 1.0 - alphaCover); \n"
Zach Reizner01935f32015-04-29 11:15:09 -0700676"} \n";
677 // clang-format on
678
679 int i, ret = 1;
680 GLint max_texture_images, vertex_shader, fragment_shader, program, status;
681 std::string shader_log;
682
683 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_images);
684
685 for (i = 1; i <= max_texture_images; i++) {
686 std::ostringstream layer_count_formatter;
687 layer_count_formatter << i;
688 std::string layer_count(layer_count_formatter.str());
689 const GLchar *shader_sources[3] = {shader_preamble, layer_count.c_str(),
690 NULL};
691
692 shader_sources[2] = vertex_shader_source;
693 vertex_shader = CompileAndCheckShader(GL_VERTEX_SHADER, 3, shader_sources,
694 ret ? &shader_log : NULL);
695 if (!vertex_shader) {
696 if (ret) {
697 ALOGE("Failed to make vertex shader:\n%s", shader_log.c_str());
698 }
699 break;
700 }
701
702 shader_sources[2] = fragment_shader_source;
703 fragment_shader = CompileAndCheckShader(
704 GL_FRAGMENT_SHADER, 3, shader_sources, ret ? &shader_log : NULL);
705 if (!fragment_shader) {
706 if (ret) {
707 ALOGE("Failed to make fragment shader:\n%s", shader_log.c_str());
708 }
709 goto delete_vs;
710 }
711
712 program = glCreateProgram();
713 if (!program) {
714 if (ret)
715 ALOGE("Failed to create program %s", get_gl_error());
716 goto delete_fs;
717 }
718
719 glAttachShader(program, vertex_shader);
720 glAttachShader(program, fragment_shader);
721 glBindAttribLocation(program, 0, "vPosition");
722 glBindAttribLocation(program, 1, "vTexCoords");
723 glLinkProgram(program);
724 glDetachShader(program, vertex_shader);
725 glDeleteShader(vertex_shader);
726 glDetachShader(program, fragment_shader);
727 glDeleteShader(fragment_shader);
728
729 glGetProgramiv(program, GL_LINK_STATUS, &status);
730 if (!status) {
731 if (ret) {
732 GLint log_length;
733 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
734 std::string program_log(log_length, ' ');
735 glGetProgramInfoLog(program, log_length, NULL, &program_log[0]);
736 ALOGE("Failed to link program: \n%s", program_log.c_str());
737 }
738 glDeleteProgram(program);
739 break;
740 }
741
742 ret = 0;
743 priv_->blend_programs.push_back(program);
744
745 continue;
746
747 delete_fs:
748 glDeleteShader(fragment_shader);
749
750 delete_vs:
751 glDeleteShader(vertex_shader);
752
753 if (ret)
754 break;
755 }
756
757 return ret;
758}
759
760int GLCompositor::DoComposition(const GLComposition &composition) {
Stéphane Marchesinbe98c8c2015-06-23 16:18:10 -0700761 ATRACE_CALL();
Zach Reizner01935f32015-04-29 11:15:09 -0700762 int ret = 0;
763 size_t i;
764 std::vector<struct texture_from_handle> layer_textures;
765 std::vector<RenderingCommand> commands;
766
767 if (composition.layer_data.size() == 0) {
768 return -EALREADY;
769 }
770
771 if (BeginContext()) {
772 return -EINVAL;
773 }
774
775 GLTarget *target = &priv_->targets[composition.target_handle];
776 GLint frame_width = target->fb->getWidth();
777 GLint frame_height = target->fb->getHeight();
778 EGLSyncKHR finished_sync;
779
780 for (i = 0; i < composition.layer_data.size(); i++) {
781 const struct hwc_layer_1 *layer = &composition.layer_data[i].layer;
782
783 if (ret) {
784 if (layer->acquireFenceFd >= 0)
785 close(layer->acquireFenceFd);
786 continue;
787 }
788
789 layer_textures.push_back(texture_from_handle());
790 ret = CreateTextureFromHandle(layer->handle, &layer_textures.back());
791 if (!ret) {
792 ret = DoFenceWait(layer->acquireFenceFd);
793 }
794 if (ret) {
795 layer_textures.pop_back();
796 ret = -EINVAL;
797 }
798 }
799
800 if (ret) {
801 goto destroy_textures;
802 }
803
804 ConstructCommands(composition, &commands);
805
806 glBindFramebuffer(GL_FRAMEBUFFER, target->gl_fb);
807
808 glViewport(0, 0, frame_width, frame_height);
809
Zach Reiznerdb556112015-06-11 11:30:20 -0700810 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Zach Reizner01935f32015-04-29 11:15:09 -0700811 glClear(GL_COLOR_BUFFER_BIT);
812
813 glBindBuffer(GL_ARRAY_BUFFER, priv_->vertex_buffer);
814 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, NULL);
815 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4,
816 (void *)(sizeof(float) * 2));
817 glEnableVertexAttribArray(0);
818 glEnableVertexAttribArray(1);
819
820 for (std::vector<RenderingCommand>::iterator it = commands.begin();
821 it != commands.end(); ++it) {
822 const RenderingCommand &cmd = *it;
823
824 if (cmd.texture_count <= 0) {
825 continue;
826 }
827
828 // TODO(zachr): handle the case of too many overlapping textures for one
829 // area by falling back to rendering as many layers as possible using
830 // multiple blending passes.
831 if (cmd.texture_count > priv_->blend_programs.size()) {
832 ALOGE("Too many layers to render in one area");
833 continue;
834 }
835
836 GLint program = priv_->blend_programs[cmd.texture_count - 1];
837 glUseProgram(program);
838 GLint gl_viewport_loc = glGetUniformLocation(program, "uViewport");
839 GLint gl_tex_loc = glGetUniformLocation(program, "uLayerTextures");
840 GLint gl_crop_loc = glGetUniformLocation(program, "uLayerCrop");
841 GLint gl_alpha_loc = glGetUniformLocation(program, "uLayerAlpha");
842 glUniform4f(gl_viewport_loc, cmd.bounds[0] / (float)frame_width,
843 cmd.bounds[1] / (float)frame_height,
844 (cmd.bounds[2] - cmd.bounds[0]) / (float)frame_width,
845 (cmd.bounds[3] - cmd.bounds[1]) / (float)frame_height);
846
847 for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
848 const RenderingCommand::TextureSource &src = cmd.textures[src_index];
849 glUniform1f(gl_alpha_loc + src_index, src.alpha);
850 glUniform4f(gl_crop_loc + src_index, src.crop_bounds[0],
851 src.crop_bounds[1], src.crop_bounds[2] - src.crop_bounds[0],
852 src.crop_bounds[3] - src.crop_bounds[1]);
853
854 glUniform1i(gl_tex_loc + src_index, src_index);
855 glActiveTexture(GL_TEXTURE0 + src_index);
856 glBindTexture(GL_TEXTURE_2D, layer_textures[src.texture_index].texture);
857 }
858
859 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
860
861 for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
862 glActiveTexture(GL_TEXTURE0 + src_index);
863 glBindTexture(GL_TEXTURE_2D, 0);
864 }
865 }
866
867 glActiveTexture(GL_TEXTURE0);
868 glDisableVertexAttribArray(0);
869 glDisableVertexAttribArray(1);
870 glBindBuffer(GL_ARRAY_BUFFER, 0);
871 glUseProgram(0);
872
873 glBindFramebuffer(GL_FRAMEBUFFER, 0);
874
875 finished_sync =
876 eglCreateSyncKHR(priv_->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
877 if (finished_sync != EGL_NO_SYNC_KHR) {
878 glFlush(); // Creates the syncpoint
879 ret = eglDupNativeFenceFDANDROID(priv_->egl_display, finished_sync);
880 eglDestroySyncKHR(priv_->egl_display, finished_sync);
881 if (ret != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
882 goto destroy_textures;
883 }
884 }
885
886 // Used as a fallback if the native sync fence fails.
887 ret = -EALREADY;
888 glFinish();
889
890destroy_textures:
891 for (i = 0; i < layer_textures.size(); i++)
892 DestroyTextureFromHandle(layer_textures[i]);
893
894 EndContext();
895
896 return ret;
897}
898
899int GLCompositor::DoFenceWait(int acquireFenceFd) {
900 int ret = 0;
901
902 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, acquireFenceFd,
903 EGL_NONE};
904 EGLSyncKHR egl_sync = eglCreateSyncKHR(
905 priv_->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
906 if (egl_sync == EGL_NO_SYNC_KHR) {
907 ALOGE("Failed to make EGLSyncKHR from acquireFenceFd: %s", get_egl_error());
908 close(acquireFenceFd);
909 return 1;
910 }
911
912 EGLint success = eglWaitSyncKHR(priv_->egl_display, egl_sync, 0);
913 if (success == EGL_FALSE) {
914 ALOGE("Failed to wait for acquire: %s", get_egl_error());
915 ret = 1;
916 }
917 eglDestroySyncKHR(priv_->egl_display, egl_sync);
918
919 return ret;
920}
921
922int GLCompositor::CreateTextureFromHandle(buffer_handle_t handle,
923 struct texture_from_handle *tex) {
924 EGLImageKHR image = eglCreateImageKHR(
925 priv_->egl_display, EGL_NO_CONTEXT, EGL_NATIVE_HANDLE_ANDROID_NVX,
926 (EGLClientBuffer)handle, NULL /* no attribs */);
927
928 if (image == EGL_NO_IMAGE_KHR) {
929 ALOGE("Failed to make image %s %p", get_egl_error(), handle);
930 return 1;
931 }
932
933 glGenTextures(1, &tex->texture);
934 glBindTexture(GL_TEXTURE_2D, tex->texture);
935 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
936 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
937 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
938 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
939 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
940
941 tex->image = image;
942
943 return 0;
944}
945
946void GLCompositor::DestroyTextureFromHandle(
947 const struct texture_from_handle &tex) {
948 glDeleteTextures(1, &tex.texture);
949 eglDestroyImageKHR(priv_->egl_display, tex.image);
950}
951
952static const char *get_gl_error(void) {
953 switch (glGetError()) {
954 case GL_NO_ERROR:
955 return "GL_NO_ERROR";
956 case GL_INVALID_ENUM:
957 return "GL_INVALID_ENUM";
958 case GL_INVALID_VALUE:
959 return "GL_INVALID_VALUE";
960 case GL_INVALID_OPERATION:
961 return "GL_INVALID_OPERATION";
962 case GL_INVALID_FRAMEBUFFER_OPERATION:
963 return "GL_INVALID_FRAMEBUFFER_OPERATION";
964 case GL_OUT_OF_MEMORY:
965 return "GL_OUT_OF_MEMORY";
966 default:
967 return "Unknown error";
968 }
969}
970
971static const char *get_egl_error(void) {
972 switch (eglGetError()) {
973 case EGL_SUCCESS:
974 return "EGL_SUCCESS";
975 case EGL_NOT_INITIALIZED:
976 return "EGL_NOT_INITIALIZED";
977 case EGL_BAD_ACCESS:
978 return "EGL_BAD_ACCESS";
979 case EGL_BAD_ALLOC:
980 return "EGL_BAD_ALLOC";
981 case EGL_BAD_ATTRIBUTE:
982 return "EGL_BAD_ATTRIBUTE";
983 case EGL_BAD_CONTEXT:
984 return "EGL_BAD_CONTEXT";
985 case EGL_BAD_CONFIG:
986 return "EGL_BAD_CONFIG";
987 case EGL_BAD_CURRENT_SURFACE:
988 return "EGL_BAD_CURRENT_SURFACE";
989 case EGL_BAD_DISPLAY:
990 return "EGL_BAD_DISPLAY";
991 case EGL_BAD_SURFACE:
992 return "EGL_BAD_SURFACE";
993 case EGL_BAD_MATCH:
994 return "EGL_BAD_MATCH";
995 case EGL_BAD_PARAMETER:
996 return "EGL_BAD_PARAMETER";
997 case EGL_BAD_NATIVE_PIXMAP:
998 return "EGL_BAD_NATIVE_PIXMAP";
999 case EGL_BAD_NATIVE_WINDOW:
1000 return "EGL_BAD_NATIVE_WINDOW";
1001 case EGL_CONTEXT_LOST:
1002 return "EGL_CONTEXT_LOST";
1003 default:
1004 return "Unknown error";
1005 }
1006}
1007
1008static bool has_extension(const char *extension, const char *extensions) {
1009 const char *start, *where, *terminator;
1010 start = extensions;
1011 for (;;) {
1012 where = (char *)strstr((const char *)start, extension);
1013 if (!where)
1014 break;
1015 terminator = where + strlen(extension);
1016 if (where == start || *(where - 1) == ' ')
1017 if (*terminator == ' ' || *terminator == '\0')
1018 return true;
1019 start = terminator;
1020 }
1021 return false;
1022}
1023
1024} // namespace android