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