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 
17 #ifndef ANDROID_FILTERFW_CORE_GL_ENV_H
18 #define ANDROID_FILTERFW_CORE_GL_ENV_H
19 
20 #include <string>
21 #include <utility>
22 #include <map>
23 
24 #include "base/logging.h"
25 #include "base/utilities.h"
26 
27 #include <GLES2/gl2.h>
28 #include <EGL/egl.h>
29 
30 #include <utils/StrongPointer.h>
31 
32 struct ANativeWindow;
33 
34 namespace android {
35 
36 class GLConsumer;
37 
38 namespace filterfw {
39 
40 class ShaderProgram;
41 class VertexFrame;
42 
43 class WindowHandle {
44   public:
~WindowHandle()45     virtual ~WindowHandle() {
46     }
47 
48     virtual void Destroy() = 0;
49 
Equals(const WindowHandle * window)50     virtual bool Equals(const WindowHandle* window) const {
51       return InternalHandle() == window->InternalHandle();
52     }
53 
54     virtual const void* InternalHandle() const = 0;
55 
56     virtual void* InternalHandle() = 0;
57 };
58 
59 // The GLEnv class provides functionality related to the EGL environment, which
60 // includes the display, context, and surface. It is possible to either create
61 // a new environment or base it off the currently active EGL environment. In
62 // order to do the latter, an EGL environment must be setup already (though not
63 // necessarily through this class), and have an active display, context, and
64 // surface.
65 class GLEnv {
66   public:
67     // Constructing and Activating /////////////////////////////////////////////
68     // Constructs a new GLEnv object. This does not create a GL context.
69     GLEnv();
70 
71     // Destructor. Tears down and deallocates any GL objects that were created
72     // by this instance.
73     ~GLEnv();
74 
75     // Inits a new GL environment, including a new surface and context. You
76     // must call Activate() before performing any GL operations.
77     bool InitWithNewContext();
78 
79     // Inits the GL environment from the current GL environment. Use this when
80     // there is already a display, surface and context available (possibly
81     // created by the host application). You do not need to call Activate() as
82     // this context is active already.
83     bool InitWithCurrentContext();
84 
85     // Activates the environment, and makes the associated GL context the
86     // current context. Creates the environment, if it has not been created
87     // already. Returns true if the activation was successful.
88     bool Activate();
89 
90     // Deactivates the environment. Returns true if the deactivation was
91     // successful. You may want to call this when moving a context to another
92     // thread. In this case, deactivate the GLEnv in the old thread, and
93     // reactivate it in the new thread.
94     bool Deactivate();
95 
96     // When rendering to a visible surface, call this to swap between the
97     // offscreen and onscreen buffers. Returns true if the buffer swap was
98     // successful.
99     bool SwapBuffers();
100 
101     // Working with Surfaces ///////////////////////////////////////////////////
102 
103     // Add a surface to the environment. This surface will now be managed (and
104     // owned) by the GLEnv instance. Returns the id of the surface.
105     int AddSurface(const EGLSurface& surface);
106 
107     // Add a window surface to the environment. The window is passed in as
108     // an opaque window handle.
109     // This surface will now be managed (and owned) by the GLEnv instance.
110     // Returns the id of the surface.
111     int AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle);
112 
113     // Switch to the surface with the specified id. This will make the surface
114     // active, if it is not active already. Specify an ID of 0 if you would like
115     // to switch to the default surface. Returns true if successful.
116     bool SwitchToSurfaceId(int surface_id);
117 
118     // Release the surface with the specified id. This will deallocate the
119     // surface. If this is the active surface, the environment will switch to
120     // the default surface (0) first. You cannot release the default surface.
121     bool ReleaseSurfaceId(int surface_id);
122 
123     // Set the timestamp for the current surface. Must be called
124     // before swapBuffers to associate the timestamp with the frame
125     // resulting from swapBuffers.
126     bool SetSurfaceTimestamp(int64_t timestamp);
127 
128     // Looks for a surface with the associated window handle. Returns -1 if no
129     // surface with such a window was found.
130     int FindSurfaceIdForWindow(const WindowHandle* window_handle);
131 
132     // Obtain the environment's EGL surface.
surface()133     const EGLSurface& surface() const {
134       return surfaces_.find(surface_id_)->second.first;
135     }
136 
137     // Working with Contexts ///////////////////////////////////////////////////
138 
139     // Add a context to the environment. This context will now be managed (and
140     // owned) by the GLEnv instance. Returns the id of the context.
141     int AddContext(const EGLContext& context);
142 
143     // Switch to the context with the specified id. This will make the context
144     // active, if it is not active already. Specify an ID of 0 if you would like
145     // to switch to the default context. Returns true if successful.
146     bool SwitchToContextId(int context_id);
147 
148     // Release the context with the specified id. This will deallocate the
149     // context. If this is the active context, the environment will switch to
150     // the default context (0) first. You cannot release the default context.
151     void ReleaseContextId(int context_id);
152 
153     // Obtain the environment's EGL context.
context()154     const EGLContext& context() const {
155       return contexts_.find(context_id_)->second;
156     }
157 
158     // Working with the Display ////////////////////////////////////////////////
159 
160     // Obtain the environment's EGL display.
display()161     const EGLDisplay& display() const {
162       return display_;
163     }
164 
165     // Inspecting the environment //////////////////////////////////////////////
166     // Returns true if the environment is active in the current thread.
167     bool IsActive() const;
168 
169     // Returns true if the environment's context is active in the curent thread.
170     bool IsContextActive() const;
171 
172     // Returns true if there is any EGL context active in the current thread.
173     // This need not be a context created by a GLEnv instance.
174     static bool IsAnyContextActive();
175 
176     // Attaching GL objects ////////////////////////////////////////////////////
177 
178     // Attach a shader to the environment. The environment takes ownership of
179     // the shader.
180     void AttachShader(int key, ShaderProgram* shader);
181 
182     // Attach a vertex frame to the environment. The environment takes ownership
183     // of the frame.
184     void AttachVertexFrame(int key, VertexFrame* frame);
185 
186     // Return the shader with the specified key, or NULL if there is no such
187     // shader attached to this environment.
188     ShaderProgram* ShaderWithKey(int key);
189 
190     // Return the vertex frame with the specified key, or NULL if there is no
191     // such frame attached to this environment.
192     VertexFrame* VertexFrameWithKey(int key);
193 
194     // Static methods //////////////////////////////////////////////////////////
195     // These operate on the currently active environment!
196 
197     // Checks if the current environment is in a GL error state. If so, it will
198     // output an error message referencing the given operation string. Returns
199     // true if there was at least one error.
200     static bool CheckGLError(const std::string& operation);
201 
202     // Checks if the current environment is in an EGL error state. If so, it
203     // will output an error message referencing the given operation string.
204     // Returns true if there was at least one error.
205     static bool CheckEGLError(const std::string& operation);
206 
207     // Get the currently used (shader) program.
208     static GLuint GetCurrentProgram();
209 
210     // Get the currently active display.
211     static EGLDisplay GetCurrentDisplay();
212 
213     // Returns the number of components for a given GL type. For instance,
214     // returns 4 for vec4, and 16 for mat4.
215     static int NumberOfComponents(GLenum type);
216 
217   private:
218     typedef std::pair<EGLSurface, WindowHandle*> SurfaceWindowPair;
219 
220     // Initializes a new GL environment.
221     bool Init();
222 
223     // Returns true if one of the Inits has been called successfully on this
224     // instance.
225     bool IsInitialized() const;
226 
227     // Outputs error messages specific to the operation eglMakeCurrent().
228     // Returns true if there was at least one error.
229     static bool CheckEGLMakeCurrentError();
230 
231     // The EGL display, contexts, and surfaces.
232     EGLDisplay display_;
233     std::map<int, EGLContext> contexts_;
234     std::map<int, SurfaceWindowPair> surfaces_;
235 
236     // The currently active context and surface ids.
237     int context_id_;
238     int surface_id_;
239 
240     // Dummy surface for context
241     sp<ANativeWindow> window_;
242 
243     // Dummy GLConsumer for context
244     sp<GLConsumer> surfaceTexture_;
245 
246     // The maximum surface id used.
247     int max_surface_id_;
248 
249     // These bools keep track of which objects this GLEnv has created (and
250     // owns).
251     bool created_context_;
252     bool created_surface_;
253     bool initialized_;
254 
255     // Attachments that GL objects can add to the environment.
256     std::map<int, ShaderProgram*> attached_shaders_;
257     std::map<int, VertexFrame*> attached_vframes_;
258 
259     GLEnv(const GLEnv&) = delete;
260     GLEnv& operator=(const GLEnv&) = delete;
261 };
262 
263 } // namespace filterfw
264 } // namespace android
265 
266 #endif  // ANDROID_FILTERFW_CORE_GL_ENV_H
267