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
32struct ANativeWindow;
33
34namespace android {
35
36class GLConsumer;
37
38namespace filterfw {
39
40class ShaderProgram;
41class VertexFrame;
42
43class WindowHandle {
44  public:
45    virtual ~WindowHandle() {
46    }
47
48    virtual void Destroy() = 0;
49
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.
65class 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.
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.
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.
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