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