blob: 5444618f74698c65c8f77c718fd74423c9e838da [file] [log] [blame]
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* 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 GLIMP_GLES_CONTEXT_H_
#define GLIMP_GLES_CONTEXT_H_
#include <GLES3/gl3.h>
#include <map>
#include <set>
#include <string>
#include <utility>
#include "glimp/egl/surface.h"
#include "glimp/gles/context_impl.h"
#include "glimp/gles/draw_state.h"
#include "glimp/gles/framebuffer.h"
#include "glimp/gles/resource_manager.h"
#include "glimp/gles/sampler.h"
#include "glimp/gles/vertex_attribute.h"
#include "nb/ref_counted.h"
#include "nb/scoped_ptr.h"
#include "starboard/atomic.h"
#include "starboard/thread.h"
namespace glimp {
namespace gles {
class Context {
public:
Context(nb::scoped_ptr<ContextImpl> context_impl, Context* share_context);
~Context() { SbAtomicNoBarrier_Store(&has_swapped_buffers_, 0); }
// Returns current thread's current context, or NULL if nothing is current.
static Context* GetTLSCurrentContext();
// Sets the current thread's current context. None of the parameters can
// be NULL (use ReleaseTLSCurrentContext() if you wish to release the current
// context).
static bool SetTLSCurrentContext(Context* context,
egl::Surface* draw,
egl::Surface* read);
// Releases the current thread's current context.
static void ReleaseTLSCurrentContext();
egl::Surface* draw_surface() {
return default_draw_framebuffer_->color_attachment_surface();
}
// Returns the thread that currently holds this Context, or kSbThreadInvalid
// if no thread currently holds the context.
SbThread current_thread() const { return current_thread_; }
// Return the last error generated and reset the error flag to GL_NO_ERROR.
GLenum GetError();
const GLubyte* GetString(GLenum name);
void GetIntegerv(GLenum pname, GLint* params);
void GetShaderiv(GLuint shader, GLenum pname, GLint* params);
void GetShaderInfoLog(GLuint shader,
GLsizei bufsize,
GLsizei* length,
GLchar* infolog);
void GetProgramiv(GLuint program, GLenum pname, GLint* params);
void GetProgramInfoLog(GLuint program,
GLsizei bufsize,
GLsizei* length,
GLchar* infolog);
void PixelStorei(GLenum pname, GLint param);
void Enable(GLenum cap);
void Disable(GLenum cap);
void ColorMask(GLboolean red,
GLboolean green,
GLboolean blue,
GLboolean alpha);
void DepthMask(GLboolean flag);
void Clear(GLbitfield mask);
void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void BlendFunc(GLenum sfactor, GLenum dfactor);
void BlendEquation(GLenum mode);
void CullFace(GLenum mode);
void FrontFace(GLenum mode);
GLuint CreateProgram();
void DeleteProgram(GLuint program);
void AttachShader(GLuint program, GLuint shader);
void LinkProgram(GLuint program);
void BindAttribLocation(GLuint program, GLuint index, const GLchar* name);
void UseProgram(GLuint program);
GLuint CreateShader(GLenum type);
void DeleteShader(GLuint shader);
void ShaderSource(GLuint shader,
GLsizei count,
const GLchar* const* string,
const GLint* length);
void CompileShader(GLuint shader);
void GenBuffers(GLsizei n, GLuint* buffers);
void GenBuffersForVideoFrame(GLsizei n, GLuint* buffers);
void DeleteBuffers(GLsizei n, const GLuint* buffers);
void BindBuffer(GLenum target, GLuint buffer);
void BufferData(GLenum target,
GLsizeiptr size,
const GLvoid* data,
GLenum usage);
void BufferSubData(GLenum target,
GLintptr offset,
GLsizeiptr size,
const GLvoid* data);
void* MapBufferRange(GLenum target,
GLintptr offset,
GLsizeiptr length,
GLbitfield access);
bool UnmapBuffer(GLenum target);
void LineWidth(GLfloat width);
void GenTextures(GLsizei n, GLuint* textures);
void DeleteTextures(GLsizei n, const GLuint* textures);
void ActiveTexture(GLenum texture);
void BindTexture(GLenum target, GLuint texture);
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params);
void TexParameteri(GLenum target, GLenum pname, GLint param);
void TexImage2D(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid* pixels);
void TexSubImage2D(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid* pixels);
void CopyTexSubImage2D(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height);
void GenFramebuffers(GLsizei n, GLuint* framebuffers);
void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
void BindFramebuffer(GLenum target, GLuint framebuffer);
void FramebufferTexture2D(GLenum target,
GLenum attachment,
GLenum textarget,
GLuint texture,
GLint level);
GLenum CheckFramebufferStatus(GLenum target);
void FramebufferRenderbuffer(GLenum target,
GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer);
void GenRenderbuffers(GLsizei n, GLuint* renderbuffers);
void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
void BindRenderbuffer(GLenum target, GLuint renderbuffer);
void RenderbufferStorage(GLenum target,
GLenum internalformat,
GLsizei width,
GLsizei height);
void StencilMask(GLuint mask);
void ClearStencil(GLint s);
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
void VertexAttribPointer(GLuint indx,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const GLvoid* ptr);
void EnableVertexAttribArray(GLuint index);
void DisableVertexAttribArray(GLuint index);
void VertexAttribfv(GLuint indx, int elem_size, const GLfloat* values);
GLint GetUniformLocation(GLuint program, const GLchar* name);
void Uniformiv(GLint location,
GLsizei count,
GLsizei elem_size,
const GLint* v);
void Uniformfv(GLint location,
GLsizei count,
GLsizei elem_size,
const GLfloat* v);
void UniformMatrixfv(GLint location,
GLsizei count,
GLboolean transpose,
GLsizei dim_size,
const GLfloat* value);
void DrawArrays(GLenum mode, GLint first, GLsizei count);
void DrawElements(GLenum mode,
GLsizei count,
GLenum type,
const GLvoid* indices);
void ReadPixels(GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
GLvoid* pixels);
void Flush();
void Finish();
void SwapBuffers();
// Called when eglBindTexImage() is called.
bool BindTextureToEGLSurface(egl::Surface* surface);
// Called when eglReleaseTexImage() is called.
bool ReleaseTextureFromEGLSurface(egl::Surface* surface);
// Utility functions for use by other modules.
nb::scoped_refptr<Texture> GetTexture(uint32_t id) {
return resource_manager_->GetTexture(id);
}
DrawStateDirtyFlags* GetDrawStateDirtyFlags() {
return &draw_state_dirty_flags_;
}
static bool has_swapped_buffers() {
return SbAtomicNoBarrier_Load(&has_swapped_buffers_) != 0;
}
private:
void MakeCurrent(egl::Surface* draw, egl::Surface* read);
void ReleaseContext();
void SetError(GLenum error) { error_ = error; }
// Returns the bound buffer for the specific specified target.
// This returns a pointer because it is used by glBindBuffer() which modifies
// what the returned scoped_refptr points to.
nb::scoped_refptr<Buffer>* GetBoundBufferForTarget(GLenum target);
// Returns the bound texture for the specific specified target and slot.
// This returns a pointer because it is used by glBindTexture() which modifies
// what the returned scoped_refptr points to.
nb::scoped_refptr<Texture>* GetBoundTextureForTarget(GLenum target,
GLenum texture);
void SetupExtensionsString();
void UpdateVertexAttribsInDrawState();
void UpdateSamplersInDrawState();
// Packs enabled vertex attributes and samplers into dense lists in the
// |draw_state_| if they have been modified.
void CompressDrawStateForDrawCall();
// Marks the used program as being dirty, but this may also imply the marking
// of attributes and uniforms as being dirty as well.
void MarkUsedProgramDirty();
// Sets the bound framebuffer to the default framebuffer (e.g. when
// glBindFramebuffer(GL_FRAMEBUFFER, 0) is called).
void SetBoundDrawFramebufferToDefault();
void SetBoundReadFramebufferToDefault();
bool IsDefaultDrawFramebufferBound() const;
bool IsDefaultReadFramebufferBound() const;
// Takes settings like GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT into
// account to determine the pitch of incoming pixel data.
int GetPitchForTextureData(int width, PixelFormat pixel_format) const;
// A reference to the platform-specific implementation aspects of the context.
nb::scoped_ptr<ContextImpl> impl_;
// The thread that currently holds this context as its current context.
SbThread current_thread_;
// Has this context ever been made current before?
bool has_been_current_;
// The value to be returned when GetString(GL_EXTENSIONS) is called.
std::string extensions_string_;
// The resource manager containing all referenced resources.
nb::scoped_refptr<ResourceManager> resource_manager_;
// Sets the active texture, which can be thought of more intuitively as
// the active "sampler". Set using glActiveTexture().
GLenum active_texture_;
// The set of sampler units, of which |active_texture_| indexes.
nb::scoped_array<nb::scoped_refptr<Texture> > texture_units_;
bool enabled_textures_dirty_;
// A mapping from an integer index (specified by the index parameter of
// glBindAttribLocation(), glVertexAttribPointer(), and others) to vertex
// attribute information structure.
std::map<unsigned int, VertexAttributeArray> vertex_attrib_map_;
// This map is populated by calls to glVertexAttribXfv() and contains
// attribute values that, when used, should apply to ALL vertices in a draw
// call. These attribute values will be used instead of those set by
// glVertexAttribPointer() whenever the corresponding vertex attribute id
// (the key of this map) attribute array is disabled through a call to
// glDisableVertexAttribArray().
std::map<unsigned int, VertexAttributeConstant> const_vertex_attrib_map_;
// Keeps track of which vertex attributes are enabled. This set is modified
// through calls to glEnableVertexAttribArray() and
// glDisableVertexAttribArray().
std::set<unsigned int> enabled_vertex_attribs_;
bool enabled_vertex_attribs_dirty_;
// The default draw and read framebuffer are those whose surfaces are set by
// calls to eglMakeCurrent(). The default draw framebuffer is the initial
// framebuffer target for draw commands, and can be selected by calling
// glBindFramebuffer(0).
nb::scoped_refptr<Framebuffer> default_draw_framebuffer_;
nb::scoped_refptr<Framebuffer> default_read_framebuffer_;
// The currently bound read framebuffer. If this is set to the default read
// framebuffer, then it will be equal to |default_read_framebuffer_|.
nb::scoped_refptr<Framebuffer> read_framebuffer_;
// Tracks all GL draw state. It is updated by making various GL calls,
// and it is read when a draw (or clear) call is made. It is modified
// by this Context object and read from the ContextImpl object.
DrawState draw_state_;
// Tracks which members of |draw_state_| have been modified since the last
// draw (or clear) command issued to the ContextImpl object. This
// allows implementations to determine whether it is necessary to re-setup
// certain context information. It is expected that implementations will
// set these dirty flags to false after they have processed the corresponding
// draw state.
DrawStateDirtyFlags draw_state_dirty_flags_;
// The pack/unpack alignments are used when transferring pixel data to/from
// client CPU memory, respectively. For example, calls to glTexImage2D()
// will refer to the unpack alignment to determine the expected alignment
// of each row of pixel data. These values are set through glPixelStorei().
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml
int pack_alignment_;
int unpack_alignment_;
// Allows the pitch of texture data to be explicitly specified. This value
// can be modified by calling glPixelStorei(GL_UNPACK_ALIGNMENT, x).
// https://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml
int unpack_row_length_;
// Tracks the currently bound pixel unpack buffer object, or NULL if none
// are bound.
nb::scoped_refptr<Buffer> bound_pixel_unpack_buffer_;
// Keeps track of the set of EGLSurfaces that are bound to textures
// currently.
std::map<egl::Surface*, nb::scoped_refptr<Texture> > bound_egl_surfaces_;
// The currently bound renderbuffer, specified through a call to
// glBindRenderbuffer().
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindRenderbuffer.xml
nb::scoped_refptr<Renderbuffer> bound_renderbuffer_;
// The last GL ES error raised.
GLenum error_;
// Track if SwapBuffers() has been called. Stores 0 if SwapBuffers() has not
// been called, and 1 if SwapBuffers() has been called.
static SbAtomic32 has_swapped_buffers_;
};
} // namespace gles
} // namespace glimp
#endif // GLIMP_GLES_CONTEXT_H_