blob: dcc8c3cb7b482a36a352d5202ef9ad45a4bffb3d [file] [log] [blame]
// Copyright 2017 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 COBALT_RENDERER_RASTERIZER_EGL_GRAPHICS_STATE_H_
#define COBALT_RENDERER_RASTERIZER_EGL_GRAPHICS_STATE_H_
#include <GLES2/gl2.h>
#include <vector>
#include "base/basictypes.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect.h"
#include "cobalt/math/size.h"
#include "cobalt/renderer/backend/render_target.h"
namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace egl {
// Class representing all the GL graphics states pertinent to rendering. This
// caches the state information and helps reduce redundant GL calls.
class GraphicsState {
public:
GraphicsState();
~GraphicsState();
// Mark all cached states as dirty. GL commands to reset the state will be
// executed on the next call to Clear or UseProgram.
void SetDirty();
// Specify the beginning of a new render frame.
void BeginFrame();
// Specify the end of the current render frame.
void EndFrame();
// Clear the color and depth buffers.
void Clear();
void Clear(float r, float g, float b, float a);
// Set the current shader program to be used.
void UseProgram(GLuint program);
GLuint GetProgram() const { return program_; }
// Bind the specified framebuffer. This only goes through glBindFramebuffer
// and does not call eglMakeCurrent. This also SetClipAdjustment() to the
// render target's dimensions.
// |render_target| may be null to unbind the current framebuffer.
// NOTE: Be sure to call Viewport() and Scissor() after binding a new
// framebuffer.
void BindFramebuffer(const backend::RenderTarget* render_target);
// Set the viewport. If changing render targets, then be sure to
// BindFramebuffer() before calling this.
void Viewport(int x, int y, int width, int height);
const math::Rect& GetViewport() const { return viewport_; }
// Set the scissor box. If changing render targets, then be sure to
// BindFramebuffer() before calling this.
void Scissor(int x, int y, int width, int height);
const math::Rect& GetScissor() const { return scissor_; }
// Control blending state.
// Default = disabled.
void EnableBlend();
void DisableBlend();
bool IsBlendEnabled() const { return blend_enabled_; }
// Bind a texture to a given texture unit. Combines glActiveTexture and
// glBindTexture.
void ActiveBindTexture(GLenum texture_unit, GLenum target, GLuint texture);
// Bind a texture to the specified texture unit and set its texture wrap
// mode.
void ActiveBindTexture(GLenum texture_unit, GLenum target, GLuint texture,
GLint texture_wrap_mode);
// Update the GPU with the current clip adjustment settings.
void UpdateClipAdjustment(GLint handle);
// Update the GPU with the specified transform matrix.
void UpdateTransformMatrix(GLint handle, const math::Matrix3F& transform);
// Reserve the specified number of bytes for vertex data in the upcoming
// frame. This must be called outside of a render frame (i.e. before
// BeginFrame / after EndFrame).
void ReserveVertexData(size_t bytes);
// Returns a client-side pointer to the specified number of bytes in the
// vertex data buffer. The number of bytes allocated for any given frame
// should be less than or equal to the number of bytes reserved. This must
// be done after all calls to ReserveVertexData for a given render frame.
uint8_t* AllocateVertexData(size_t bytes);
// Update the GPU with the current contents of the vertex data buffer. This
// should only be called once, after BeginFrame().
void UpdateVertexData();
// Specify vertex attribute data that the current program will use.
// |client_pointer| should be within the range of addresses returned by
// AllocateVertexData.
void VertexAttribPointer(GLint index, GLint size, GLenum type,
GLboolean normalized, GLsizei stride, const void* client_pointer);
// Disable any vertex attrib arrays that the previous program used (via
// VertexAttribPointer), but the current program does not.
void VertexAttribFinish();
private:
void Reset();
// Set the clip adjustment to be used with vertex shaders. This transforms
// the vertex coordinates from view space to clip space.
void SetClipAdjustment();
math::Rect viewport_;
math::Rect scissor_;
math::Size render_target_size_;
GLuint render_target_handle_;
int32_t render_target_serial_;
GLuint program_;
GLuint array_buffer_handle_;
GLenum texture_unit_;
uint32_t enabled_vertex_attrib_array_mask_;
uint32_t disable_vertex_attrib_array_mask_;
float clip_adjustment_[4];
bool clip_adjustment_dirty_;
bool state_dirty_;
bool blend_enabled_;
static const int kNumTextureUnitsCached = 8;
GLenum texunit_target_[kNumTextureUnitsCached];
GLuint texunit_texture_[kNumTextureUnitsCached];
static const int kNumFramesBuffered = 3;
int frame_index_;
static const size_t kVertexDataAlignment = 4;
std::vector<uint8_t> vertex_data_buffer_;
size_t vertex_data_reserved_;
size_t vertex_data_allocated_;
GLuint vertex_data_buffer_handle_[kNumFramesBuffered];
bool vertex_data_buffer_updated_;
};
} // namespace egl
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt
#endif // COBALT_RENDERER_RASTERIZER_EGL_GRAPHICS_STATE_H_