blob: a8c48f40cb09856e3f2e543aa93b5ee3f018b295 [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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
#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"
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 {
// 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();
// Set the current shader program to be used.
void UseProgram(GLuint program);
GLuint GetProgram() const { return program_; }
// Set the viewport.
void Viewport(int x, int y, int width, int height);
const math::Rect& GetViewport() const { return viewport_; }
// Set the scissor box.
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_; }
// Control depth testing.
// Default = enabled.
void EnableDepthTest();
void DisableDepthTest();
bool IsDepthTestEnabled() const { return depth_test_enabled_; }
// Control writing to the depth buffer.
// Default = enabled.
void EnableDepthWrite();
void DisableDepthWrite();
bool IsDepthWriteEnabled() const { return depth_write_enabled_; }
// Reset to the default depth function.
void ResetDepthFunc();
// 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);
// Set the clip adjustment to be used with vertex shaders. This transforms
// the vertex coordinates from view space to clip space.
void SetClipAdjustment(const math::Size& render_target_size);
// 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();
// Return the farthest depth value.
static float FarthestDepth();
// Return the next closest depth value. Vertices using the output depth are
// guaranteed to render on top of vertices using the incoming depth.
static float NextClosestDepth(float depth);
void Reset();
math::Rect viewport_;
math::Rect scissor_;
math::Size render_target_size_;
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_;
bool depth_test_enabled_;
bool depth_write_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