blob: 5e444412fbed90802b14b213b2afd8c473bc18ea [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. 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 <memory>
#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"
#include "cobalt/renderer/egl_and_gles.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();
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);
// 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);
// 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);
// Reserve the specified number of vertex indices for the upcoming frame.
// This must be called outside of a render frame.
void ReserveVertexIndices(size_t count);
// Returns a client-side pointer to the specified number of vertex indices.
// These indices should have been reserved using ReserveVertexIndices.
// Allocations can only be made after all calls to reserve indices for a
// given frame.
uint16_t* AllocateVertexIndices(size_t count);
// Return a pointer to a previously allocated vertex index buffer. The return
// value is suitable for use with glDrawElements.
const GLvoid* GetVertexIndexPointer(const uint16_t* client_pointer);
// Update the GPU with the current contents of the vertex data and index
// buffers. This should only be called once, after BeginFrame().
void UpdateVertexBuffers();
// 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();
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_;
GLuint index_buffer_handle_;
GLenum texture_unit_;
GLint max_vertex_attribs_;
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::unique_ptr<uint8_t[]> vertex_data_buffer_;
size_t vertex_data_capacity_;
size_t vertex_data_reserved_;
size_t vertex_data_allocated_;
GLuint vertex_data_buffer_handle_[kNumFramesBuffered];
std::unique_ptr<uint16_t[]> vertex_index_buffer_;
size_t vertex_index_capacity_;
size_t vertex_index_reserved_;
size_t vertex_index_allocated_;
GLuint vertex_index_buffer_handle_[kNumFramesBuffered];
bool vertex_buffers_updated_;
} // namespace egl
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt