1 /*
2  * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of The Linux Foundation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <vector>
31 #include <string>
32 
33 #include "gl_common.h"
34 
35 #define __CLASS__ "GLCommon"
36 
37 namespace sdm {
38 
LoadProgram(int vertex_entries,const char ** vertex,int fragment_entries,const char ** fragment)39 GLuint GLCommon::LoadProgram(int vertex_entries, const char **vertex, int fragment_entries,
40                            const char **fragment) {
41   GLuint prog_id = glCreateProgram();
42 
43   int vert_id = glCreateShader(GL_VERTEX_SHADER);
44   int frag_id = glCreateShader(GL_FRAGMENT_SHADER);
45 
46   GL(glShaderSource(vert_id, vertex_entries, vertex, 0));
47   GL(glCompileShader(vert_id));
48   DumpShaderLog(vert_id);
49 
50   GL(glShaderSource(frag_id, fragment_entries, fragment, 0));
51   GL(glCompileShader(frag_id));
52   DumpShaderLog(frag_id);
53 
54   GL(glAttachShader(prog_id, vert_id));
55   GL(glAttachShader(prog_id, frag_id));
56 
57   GL(glLinkProgram(prog_id));
58 
59   GL(glDetachShader(prog_id, vert_id));
60   GL(glDetachShader(prog_id, frag_id));
61 
62   GL(glDeleteShader(vert_id));
63   GL(glDeleteShader(frag_id));
64 
65   return prog_id;
66 }
67 
DumpShaderLog(int shader)68 void GLCommon::DumpShaderLog(int shader) {
69   int success = 0;
70   GLchar infoLog[512];
71   GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));
72   if (!success) {
73     glGetShaderInfoLog(shader, 512, NULL, infoLog);
74     DLOGI("Shader Failed to compile: %s\n", infoLog);
75   }
76 }
77 
MakeCurrent(const GLContext * ctx)78 void GLCommon::MakeCurrent(const GLContext* ctx) {
79   DTRACE_SCOPED();
80   EGL(eglMakeCurrent(ctx->egl_display, ctx->egl_surface, ctx->egl_surface, ctx->egl_context));
81 }
82 
SetProgram(uint32_t id)83 void GLCommon::SetProgram(uint32_t id) {
84   DTRACE_SCOPED();
85   GL(glUseProgram(id));
86 }
87 
DeleteProgram(uint32_t id)88 void GLCommon::DeleteProgram(uint32_t id) {
89   DTRACE_SCOPED();
90   GL(glDeleteProgram(id));
91 }
92 
SetSourceBuffer(const private_handle_t * src_hnd)93 void GLCommon::SetSourceBuffer(const private_handle_t *src_hnd) {
94   DTRACE_SCOPED();
95   EGLImageBuffer *src_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(src_hnd));
96 
97   GL(glActiveTexture(GL_TEXTURE0));
98   if (src_buffer) {
99     GL(glBindTexture(GL_TEXTURE_2D, src_buffer->getTexture(GL_TEXTURE_2D)));
100   }
101 }
102 
SetDestinationBuffer(const private_handle_t * dst_hnd)103 void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd) {
104   DTRACE_SCOPED();
105   EGLImageBuffer *dst_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(dst_hnd));
106 
107   if (dst_buffer) {
108     GL(glBindFramebuffer(GL_FRAMEBUFFER, dst_buffer->getFramebuffer()));
109   }
110 }
111 
WaitOnInputFence(const std::vector<shared_ptr<Fence>> & in_fences)112 int GLCommon::WaitOnInputFence(const std::vector<shared_ptr<Fence>> &in_fences) {
113   DTRACE_SCOPED();
114 
115   shared_ptr<Fence> in_fence = Fence::Merge(in_fences, true /* ignore signaled*/);
116   if (in_fence == nullptr) {
117    return 0;
118   }
119 
120   int fd = Fence::Dup(in_fence);
121   EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
122   EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID,
123                                      attribs);
124 
125   if (sync == EGL_NO_SYNC_KHR) {
126     DLOGE("Failed to create sync from source fd: %s", Fence::GetStr(in_fence).c_str());
127     close(fd);
128     return -1;
129   }
130 
131   EGL(eglWaitSyncKHR(eglGetCurrentDisplay(), sync, 0));
132   EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
133 
134   return 0;
135 }
136 
CreateOutputFence(shared_ptr<Fence> * out_fence)137 int GLCommon::CreateOutputFence(shared_ptr<Fence> *out_fence) {
138   DTRACE_SCOPED();
139   EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
140 
141   // Swap buffer.
142   GL(glFlush());
143 
144   if (sync == EGL_NO_SYNC_KHR) {
145     DLOGE("Failed to create egl sync fence");
146     return -1;
147   }
148 
149   int status = 0;
150   int fd = eglDupNativeFenceFDANDROID(eglGetCurrentDisplay(), sync);
151   if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
152     status = -1;
153     DLOGE("Failed to dup sync");
154   } else {
155     *out_fence = Fence::Create(fd, "gl_out_fence");
156   }
157   EGL(eglDestroySyncKHR(eglGetCurrentDisplay(), sync));
158 
159   return status;
160 }
161 
DestroyContext(GLContext * ctx)162 void GLCommon::DestroyContext(GLContext* ctx) {
163   DTRACE_SCOPED();
164 
165   // Clear egl image buffers.
166   image_wrapper_.Deinit();
167 
168   EGL(DeleteProgram(ctx->program_id));
169   EGL(eglMakeCurrent(ctx->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
170   EGL(eglDestroySurface(ctx->egl_display, ctx->egl_surface));
171   EGL(eglDestroyContext(ctx->egl_display, ctx->egl_context));
172   EGL(eglTerminate(ctx->egl_display));
173 }
174 
ClearCache()175 void GLCommon::ClearCache() {
176   // Clear cached handles.
177   image_wrapper_.Deinit();
178   image_wrapper_.Init();
179 }
180 
SetRealTimePriority()181 void GLCommon::SetRealTimePriority() {
182   // same as composer thread
183   struct sched_param param = {0};
184   param.sched_priority = 2;
185   if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
186     DLOGE("Couldn't set SCHED_FIFO: %d", errno);
187   }
188 }
189 
SetViewport(const GLRect & dst_rect)190 void GLCommon::SetViewport(const GLRect &dst_rect) {
191   DTRACE_SCOPED();
192   float width = dst_rect.right - dst_rect.left;
193   float height = dst_rect.bottom - dst_rect.top;
194   GL(glViewport(dst_rect.left, dst_rect.top, width, height));
195 }
196 
197 }  // namespace sdm
198 
199