xref: /aosp_15_r20/frameworks/base/media/mca/filterfw/native/core/gl_env.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2011 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 // #define LOG_NDEBUG 0
17 
18 #include "core/gl_env.h"
19 
20 #include <EGL/eglext.h>
21 #include <com_android_graphics_libgui_flags.h>
22 #include <gui/BufferQueue.h>
23 #include <gui/GLConsumer.h>
24 #include <gui/IGraphicBufferProducer.h>
25 #include <gui/Surface.h>
26 
27 #include <map>
28 #include <string>
29 
30 #include "base/logging.h"
31 #include "base/utilities.h"
32 #include "core/shader_program.h"
33 #include "core/vertex_frame.h"
34 #include "system/window.h"
35 
36 namespace android {
37 namespace filterfw {
38 
GLEnv()39 GLEnv::GLEnv()
40   : display_(EGL_NO_DISPLAY),
41     context_id_(0),
42     surface_id_(0),
43     max_surface_id_(0),
44     created_context_(false),
45     created_surface_(false),
46     initialized_(false) {
47 }
48 
~GLEnv()49 GLEnv::~GLEnv() {
50   // Destroy surfaces
51   for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
52        it != surfaces_.end();
53        ++it) {
54     if (it->first != 0 || created_surface_) {
55       eglDestroySurface(display(), it->second.first);
56       if (it->second.second) {
57         it->second.second->Destroy();
58         delete it->second.second;
59       }
60     }
61   }
62 
63   // Destroy contexts
64   for (std::map<int, EGLContext>::iterator it = contexts_.begin();
65        it != contexts_.end();
66        ++it) {
67     if (it->first != 0 || created_context_)
68       eglDestroyContext(display(), it->second);
69   }
70 
71   // Destroy attached shaders and frames
72   STLDeleteValues(&attached_shaders_);
73   STLDeleteValues(&attached_vframes_);
74 
75   // Destroy display
76   if (initialized_)
77     eglTerminate(display());
78 
79   // Log error if this did not work
80   if (CheckEGLError("TearDown!"))
81     ALOGE("GLEnv: Error tearing down GL Environment!");
82 }
83 
IsInitialized() const84 bool GLEnv::IsInitialized() const {
85   return (contexts_.size() > 0 &&
86           surfaces_.size() > 0 &&
87           display_ != EGL_NO_DISPLAY);
88 }
89 
Deactivate()90 bool GLEnv::Deactivate() {
91   eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
92   return !CheckEGLError("eglMakeCurrent");
93 }
94 
Activate()95 bool GLEnv::Activate() {
96   ALOGV("Activate()");
97   if (display()   != eglGetCurrentDisplay() ||
98       context()   != eglGetCurrentContext() ||
99       surface()   != eglGetCurrentSurface(EGL_DRAW)) {
100     // Make sure we are initialized
101     if (context() == EGL_NO_CONTEXT || surface() == EGL_NO_SURFACE)
102       return false;
103 
104     // Make our context current
105     ALOGV("eglMakeCurrent");
106     eglMakeCurrent(display(), surface(), surface(), context());
107 
108     return !CheckEGLMakeCurrentError();
109   }
110   return true;
111 }
112 
SwapBuffers()113 bool GLEnv::SwapBuffers() {
114   const bool result = eglSwapBuffers(display(), surface()) == EGL_TRUE;
115   return !CheckEGLError("eglSwapBuffers") && result;
116 }
117 
InitWithCurrentContext()118 bool GLEnv::InitWithCurrentContext() {
119   if (IsInitialized())
120     return true;
121 
122   display_     = eglGetCurrentDisplay();
123   contexts_[0] = eglGetCurrentContext();
124   surfaces_[0] = SurfaceWindowPair(eglGetCurrentSurface(EGL_DRAW), NULL);
125 
126   return (context() != EGL_NO_CONTEXT) &&
127          (display() != EGL_NO_DISPLAY) &&
128          (surface() != EGL_NO_SURFACE);
129 }
130 
InitWithNewContext()131 bool GLEnv::InitWithNewContext() {
132   if (IsInitialized()) {
133     ALOGE("GLEnv: Attempting to reinitialize environment!");
134     return false;
135   }
136 
137   display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
138   if (CheckEGLError("eglGetDisplay")) return false;
139 
140   EGLint majorVersion;
141   EGLint minorVersion;
142   eglInitialize(display(), &majorVersion, &minorVersion);
143   if (CheckEGLError("eglInitialize")) return false;
144   initialized_ = true;
145 
146   // Configure context/surface
147   EGLConfig config;
148   EGLint numConfigs = -1;
149 
150   // TODO(renn): Do we need the window bit here?
151   // TODO: Currently choosing the config that includes all
152   // This is not needed if the encoding is not being used
153   EGLint configAttribs[] = {
154     EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
155     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
156     EGL_RED_SIZE, 8,
157     EGL_GREEN_SIZE, 8,
158     EGL_BLUE_SIZE, 8,
159     EGL_RECORDABLE_ANDROID, EGL_TRUE,
160     EGL_NONE
161   };
162 
163   eglChooseConfig(display(), configAttribs, &config, 1, &numConfigs);
164   if (numConfigs < 1) {
165     ALOGE("GLEnv::Init: No suitable EGL configuration found!");
166     return false;
167   }
168 
169   // Create dummy surface using a GLConsumer
170 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
171   surfaceTexture_ = new GLConsumer(0, GLConsumer::TEXTURE_EXTERNAL, /*useFenceSync=*/true,
172                                    /*isControlledByApp=*/false);
173   window_ = surfaceTexture_->getSurface();
174 #else
175   sp<IGraphicBufferProducer> producer;
176   sp<IGraphicBufferConsumer> consumer;
177   BufferQueue::createBufferQueue(&producer, &consumer);
178   surfaceTexture_ = new GLConsumer(consumer, 0, GLConsumer::TEXTURE_EXTERNAL,
179           true, false);
180   window_ = new Surface(producer);
181 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
182 
183   surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL);
184   if (CheckEGLError("eglCreateWindowSurface")) return false;
185 
186   // Create context
187   EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
188   contexts_[0] = eglCreateContext(display(),
189                                   config,
190                                   EGL_NO_CONTEXT,
191                                   context_attribs);
192   if (CheckEGLError("eglCreateContext")) return false;
193 
194   created_context_ = created_surface_ = true;
195 
196   return true;
197 }
198 
IsActive() const199 bool GLEnv::IsActive() const {
200   ALOGV("IsActive()");
201   return context() == eglGetCurrentContext()
202     &&   display() == eglGetCurrentDisplay()
203     &&   surface() == eglGetCurrentSurface(EGL_DRAW);
204 }
205 
IsContextActive() const206 bool GLEnv::IsContextActive() const {
207   return context() == eglGetCurrentContext();
208 }
209 
IsAnyContextActive()210 bool GLEnv::IsAnyContextActive() {
211   return eglGetCurrentContext() != EGL_NO_CONTEXT;
212 }
213 
AddWindowSurface(const EGLSurface & surface,WindowHandle * window_handle)214 int GLEnv::AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle) {
215   const int id = ++max_surface_id_;
216   surfaces_[id] = SurfaceWindowPair(surface, window_handle);
217   return id;
218 }
219 
AddSurface(const EGLSurface & surface)220 int GLEnv::AddSurface(const EGLSurface& surface) {
221   return AddWindowSurface(surface, NULL);
222 }
223 
SwitchToSurfaceId(int surface_id)224 bool GLEnv::SwitchToSurfaceId(int surface_id) {
225   ALOGV("SwitchToSurfaceId");
226   if (surface_id_ != surface_id) {
227     const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id);
228     if (surface) {
229       bool wasActive = IsActive();
230       surface_id_ = surface_id;
231       return wasActive ? Activate() : true;
232     }
233     return false;
234   }
235   return true;
236 }
237 
ReleaseSurfaceId(int surface_id)238 bool GLEnv::ReleaseSurfaceId(int surface_id) {
239   if (surface_id > 0) {
240     const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, surface_id);
241     if (surface_window_pair) {
242       if (surface_id_ == surface_id)
243         SwitchToSurfaceId(0);
244       eglDestroySurface(display(), surface_window_pair->first);
245       if (surface_window_pair->second) {
246         surface_window_pair->second->Destroy();
247         delete surface_window_pair->second;
248       }
249       surfaces_.erase(surface_id);
250       return true;
251     }
252   }
253   return false;
254 }
255 
SetSurfaceTimestamp(int64_t timestamp)256 bool GLEnv::SetSurfaceTimestamp(int64_t timestamp) {
257   if (surface_id_ > 0) {
258     const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_,
259             surface_id_);
260     if (surface_window_pair) {
261       ANativeWindow *window = static_cast<ANativeWindow*>(
262               surface_window_pair->second->InternalHandle());
263       native_window_set_buffers_timestamp(window, timestamp);
264       return true;
265     }
266   }
267   return false;
268 }
269 
FindSurfaceIdForWindow(const WindowHandle * window_handle)270 int GLEnv::FindSurfaceIdForWindow(const WindowHandle* window_handle) {
271   for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
272        it != surfaces_.end();
273        ++it) {
274     const WindowHandle* my_handle = it->second.second;
275     if (my_handle && my_handle->Equals(window_handle)) {
276       return it->first;
277     }
278   }
279   return -1;
280 }
281 
282 
AddContext(const EGLContext & context)283 int GLEnv::AddContext(const EGLContext& context) {
284   const int id = contexts_.size();
285   contexts_[id] = context;
286   return id;
287 }
288 
SwitchToContextId(int context_id)289 bool GLEnv::SwitchToContextId(int context_id) {
290   const EGLContext* context = FindOrNull(contexts_, context_id);
291   if (context) {
292     if (context_id_ != context_id) {
293       context_id_ = context_id;
294       return Activate();
295     }
296     return true;
297   }
298   return false;
299 }
300 
ReleaseContextId(int context_id)301 void GLEnv::ReleaseContextId(int context_id) {
302   if (context_id > 0) {
303     const EGLContext* context = FindOrNull(contexts_, context_id);
304     if (context) {
305       contexts_.erase(context_id);
306       if (context_id_ == context_id && IsActive())
307         SwitchToContextId(0);
308       eglDestroyContext(display(), *context);
309     }
310   }
311 }
312 
CheckGLError(const std::string & op)313 bool GLEnv::CheckGLError(const std::string& op) {
314   bool err = false;
315   for (GLint error = glGetError(); error; error = glGetError()) {
316     ALOGE("GL Error: Operation '%s' caused GL error (0x%x)\n",
317          op.c_str(),
318          error);
319     err = true;
320   }
321   return err;
322 }
323 
CheckEGLError(const std::string & op)324 bool GLEnv::CheckEGLError(const std::string& op) {
325   bool err = false;
326   for (EGLint error = eglGetError();
327        error != EGL_SUCCESS;
328        error = eglGetError()) {
329     ALOGE("EGL Error: Operation '%s' caused EGL error (0x%x)\n",
330          op.c_str(),
331          error);
332     err = true;
333   }
334   return err;
335 }
336 
CheckEGLMakeCurrentError()337 bool GLEnv::CheckEGLMakeCurrentError() {
338   bool err = false;
339   for (EGLint error = eglGetError();
340        error != EGL_SUCCESS;
341        error = eglGetError()) {
342     switch (error) {
343       case EGL_BAD_DISPLAY:
344         ALOGE("EGL Error: Attempting to activate context with bad display!");
345         break;
346       case EGL_BAD_SURFACE:
347         ALOGE("EGL Error: Attempting to activate context with bad surface!");
348         break;
349       case EGL_BAD_ACCESS:
350         ALOGE("EGL Error: Attempting to activate context, which is "
351              "already active in another thread!");
352         break;
353       default:
354         ALOGE("EGL Error: Making EGL rendering context current caused "
355              "error: 0x%x\n", error);
356     }
357     err = true;
358   }
359   return err;
360 }
361 
GetCurrentProgram()362 GLuint GLEnv::GetCurrentProgram() {
363   GLint result;
364   glGetIntegerv(GL_CURRENT_PROGRAM, &result);
365   ALOG_ASSERT(result >= 0);
366   return static_cast<GLuint>(result);
367 }
368 
GetCurrentDisplay()369 EGLDisplay GLEnv::GetCurrentDisplay() {
370   return eglGetCurrentDisplay();
371 }
372 
NumberOfComponents(GLenum type)373 int GLEnv::NumberOfComponents(GLenum type) {
374   switch (type) {
375     case GL_BOOL:
376     case GL_FLOAT:
377     case GL_INT:
378       return 1;
379     case GL_BOOL_VEC2:
380     case GL_FLOAT_VEC2:
381     case GL_INT_VEC2:
382       return 2;
383     case GL_INT_VEC3:
384     case GL_FLOAT_VEC3:
385     case GL_BOOL_VEC3:
386       return 3;
387     case GL_BOOL_VEC4:
388     case GL_FLOAT_VEC4:
389     case GL_INT_VEC4:
390     case GL_FLOAT_MAT2:
391       return 4;
392     case GL_FLOAT_MAT3:
393       return 9;
394     case GL_FLOAT_MAT4:
395       return 16;
396     default:
397       return 0;
398   }
399 }
400 
AttachShader(int key,ShaderProgram * shader)401 void GLEnv::AttachShader(int key, ShaderProgram* shader) {
402   ShaderProgram* existingShader = ShaderWithKey(key);
403   if (existingShader)
404     delete existingShader;
405   attached_shaders_[key] = shader;
406 }
407 
AttachVertexFrame(int key,VertexFrame * frame)408 void GLEnv::AttachVertexFrame(int key, VertexFrame* frame) {
409   VertexFrame* existingFrame = VertexFrameWithKey(key);
410   if (existingFrame)
411     delete existingFrame;
412   attached_vframes_[key] = frame;
413 }
414 
ShaderWithKey(int key)415 ShaderProgram* GLEnv::ShaderWithKey(int key) {
416   return FindPtrOrNull(attached_shaders_, key);
417 }
418 
VertexFrameWithKey(int key)419 VertexFrame* GLEnv::VertexFrameWithKey(int key) {
420   return FindPtrOrNull(attached_vframes_, key);
421 }
422 
423 } // namespace filterfw
424 } // namespace android
425