blob: a709638f1c34aa344bf3b5429433603a40902ecc [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_FILTERFW_CORE_GL_ENV_H
#define ANDROID_FILTERFW_CORE_GL_ENV_H
#include <string>
#include <utility>
#include <map>
#include "base/logging.h"
#include "base/utilities.h"
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
namespace android {
class GLConsumer;
namespace filterfw {
class ShaderProgram;
class VertexFrame;
class WindowHandle {
public:
virtual ~WindowHandle() {
}
virtual void Destroy() = 0;
virtual bool Equals(const WindowHandle* window) const {
return InternalHandle() == window->InternalHandle();
}
virtual const void* InternalHandle() const = 0;
virtual void* InternalHandle() = 0;
};
// The GLEnv class provides functionality related to the EGL environment, which
// includes the display, context, and surface. It is possible to either create
// a new environment or base it off the currently active EGL environment. In
// order to do the latter, an EGL environment must be setup already (though not
// necessarily through this class), and have an active display, context, and
// surface.
class GLEnv {
public:
// Constructing and Activating /////////////////////////////////////////////
// Constructs a new GLEnv object. This does not create a GL context.
GLEnv();
// Destructor. Tears down and deallocates any GL objects that were created
// by this instance.
~GLEnv();
// Inits a new GL environment, including a new surface and context. You
// must call Activate() before performing any GL operations.
bool InitWithNewContext();
// Inits the GL environment from the current GL environment. Use this when
// there is already a display, surface and context available (possibly
// created by the host application). You do not need to call Activate() as
// this context is active already.
bool InitWithCurrentContext();
// Activates the environment, and makes the associated GL context the
// current context. Creates the environment, if it has not been created
// already. Returns true if the activation was successful.
bool Activate();
// Deactivates the environment. Returns true if the deactivation was
// successful. You may want to call this when moving a context to another
// thread. In this case, deactivate the GLEnv in the old thread, and
// reactivate it in the new thread.
bool Deactivate();
// When rendering to a visible surface, call this to swap between the
// offscreen and onscreen buffers. Returns true if the buffer swap was
// successful.
bool SwapBuffers();
// Working with Surfaces ///////////////////////////////////////////////////
// Add a surface to the environment. This surface will now be managed (and
// owned) by the GLEnv instance. Returns the id of the surface.
int AddSurface(const EGLSurface& surface);
// Add a window surface to the environment. The window is passed in as
// an opaque window handle.
// This surface will now be managed (and owned) by the GLEnv instance.
// Returns the id of the surface.
int AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle);
// Switch to the surface with the specified id. This will make the surface
// active, if it is not active already. Specify an ID of 0 if you would like
// to switch to the default surface. Returns true if successful.
bool SwitchToSurfaceId(int surface_id);
// Release the surface with the specified id. This will deallocate the
// surface. If this is the active surface, the environment will switch to
// the default surface (0) first. You cannot release the default surface.
bool ReleaseSurfaceId(int surface_id);
// Set the timestamp for the current surface. Must be called
// before swapBuffers to associate the timestamp with the frame
// resulting from swapBuffers.
bool SetSurfaceTimestamp(int64_t timestamp);
// Looks for a surface with the associated window handle. Returns -1 if no
// surface with such a window was found.
int FindSurfaceIdForWindow(const WindowHandle* window_handle);
// Obtain the environment's EGL surface.
const EGLSurface& surface() const {
return surfaces_.find(surface_id_)->second.first;
}
// Working with Contexts ///////////////////////////////////////////////////
// Add a context to the environment. This context will now be managed (and
// owned) by the GLEnv instance. Returns the id of the context.
int AddContext(const EGLContext& context);
// Switch to the context with the specified id. This will make the context
// active, if it is not active already. Specify an ID of 0 if you would like
// to switch to the default context. Returns true if successful.
bool SwitchToContextId(int context_id);
// Release the context with the specified id. This will deallocate the
// context. If this is the active context, the environment will switch to
// the default context (0) first. You cannot release the default context.
void ReleaseContextId(int context_id);
// Obtain the environment's EGL context.
const EGLContext& context() const {
return contexts_.find(context_id_)->second;
}
// Working with the Display ////////////////////////////////////////////////
// Obtain the environment's EGL display.
const EGLDisplay& display() const {
return display_;
}
// Inspecting the environment //////////////////////////////////////////////
// Returns true if the environment is active in the current thread.
bool IsActive() const;
// Returns true if the environment's context is active in the curent thread.
bool IsContextActive() const;
// Returns true if there is any EGL context active in the current thread.
// This need not be a context created by a GLEnv instance.
static bool IsAnyContextActive();
// Attaching GL objects ////////////////////////////////////////////////////
// Attach a shader to the environment. The environment takes ownership of
// the shader.
void AttachShader(int key, ShaderProgram* shader);
// Attach a vertex frame to the environment. The environment takes ownership
// of the frame.
void AttachVertexFrame(int key, VertexFrame* frame);
// Return the shader with the specified key, or NULL if there is no such
// shader attached to this environment.
ShaderProgram* ShaderWithKey(int key);
// Return the vertex frame with the specified key, or NULL if there is no
// such frame attached to this environment.
VertexFrame* VertexFrameWithKey(int key);
// Static methods //////////////////////////////////////////////////////////
// These operate on the currently active environment!
// Checks if the current environment is in a GL error state. If so, it will
// output an error message referencing the given operation string. Returns
// true if there was at least one error.
static bool CheckGLError(const std::string& operation);
// Checks if the current environment is in an EGL error state. If so, it
// will output an error message referencing the given operation string.
// Returns true if there was at least one error.
static bool CheckEGLError(const std::string& operation);
// Get the currently used (shader) program.
static GLuint GetCurrentProgram();
// Get the currently active display.
static EGLDisplay GetCurrentDisplay();
// Returns the number of components for a given GL type. For instance,
// returns 4 for vec4, and 16 for mat4.
static int NumberOfComponents(GLenum type);
private:
typedef std::pair<EGLSurface, WindowHandle*> SurfaceWindowPair;
// Initializes a new GL environment.
bool Init();
// Returns true if one of the Inits has been called successfully on this
// instance.
bool IsInitialized() const;
// Outputs error messages specific to the operation eglMakeCurrent().
// Returns true if there was at least one error.
static bool CheckEGLMakeCurrentError();
// The EGL display, contexts, and surfaces.
EGLDisplay display_;
std::map<int, EGLContext> contexts_;
std::map<int, SurfaceWindowPair> surfaces_;
// The currently active context and surface ids.
int context_id_;
int surface_id_;
// Dummy surface for context
sp<ANativeWindow> window_;
// Dummy GLConsumer for context
sp<GLConsumer> surfaceTexture_;
// The maximum surface id used.
int max_surface_id_;
// These bools keep track of which objects this GLEnv has created (and
// owns).
bool created_context_;
bool created_surface_;
bool initialized_;
// Attachments that GL objects can add to the environment.
std::map<int, ShaderProgram*> attached_shaders_;
std::map<int, VertexFrame*> attached_vframes_;
DISALLOW_COPY_AND_ASSIGN(GLEnv);
};
} // namespace filterfw
} // namespace android
#endif // ANDROID_FILTERFW_CORE_GL_ENV_H