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