UIRendererGles.h#
↰ Parent directory (OpenGLES
)
Contains implementations of functions for the classes in UIRendererGles.h.
Includes#
PVRCore/math/MathUtils.h
PVRCore/texture/Texture.h
PVRUtils/OpenGLES/SpriteGles.h
Included By#
Namespaces#
Classes#
Source Code#
#pragma once
#include "PVRUtils/OpenGLES/SpriteGles.h"
#include "PVRCore/texture/Texture.h"
#include "PVRCore/math/MathUtils.h"
namespace pvr {
namespace ui {
struct GLState
{
GLint activeProgram;
GLint activeTextureUnit;
GLint boundTexture;
GLint blendEnabled;
GLint blendSrcRgb;
GLint blendSrcAlpha;
GLint blendDstRgb;
GLint blendDstAlpha;
GLint blendEqationRgb;
GLint blendEqationAlpha;
GLboolean colorMask[4];
GLint depthTest;
GLint depthMask;
GLint stencilTest;
GLint cullingEnabled;
GLint culling;
GLint windingOrder;
GLint sampler7;
GLint vbo;
GLint ibo;
GLint vao;
std::vector<bool> vertexAttribArray;
std::vector<GLint> vertexAttribBindings;
std::vector<GLint> vertexAttribSizes;
std::vector<GLint> vertexAttribTypes;
std::vector<GLint> vertexAttribNormalized;
std::vector<GLint> vertexAttribStride;
std::vector<GLvoid*> vertexAttribOffset;
void storeCurrentGlState(Api api);
GLState()
: activeProgram(-1), activeTextureUnit(-1), boundTexture(-1), blendDstAlpha(GL_ONE), blendDstRgb(GL_ONE_MINUS_SRC_ALPHA), blendEnabled(GL_TRUE),
blendEqationAlpha(GL_FUNC_ADD), blendEqationRgb(GL_FUNC_ADD), blendSrcAlpha(GL_ZERO), blendSrcRgb(GL_SRC_ALPHA), depthMask(GL_FALSE), depthTest(GL_FALSE),
stencilTest(GL_FALSE), cullingEnabled(GL_FALSE), culling(GL_BACK), windingOrder(GL_CCW), ibo(-1), sampler7(0), vbo(-1), vao(-1), vertexAttribArray(8, GL_FALSE),
vertexAttribBindings(8, -1), vertexAttribSizes(8, -1), vertexAttribTypes(8, -1), vertexAttribNormalized(8, -1), vertexAttribStride(8, -1),
vertexAttribOffset(8, static_cast<GLvoid*>(nullptr))
{
colorMask[0] = GL_TRUE;
colorMask[1] = GL_TRUE;
colorMask[2] = GL_TRUE;
colorMask[3] = GL_TRUE;
}
};
struct GLStateTracker : public GLState
{
bool activeProgramChanged;
bool activeTextureUnitChanged;
bool boundTextureChanged;
bool blendEnabledChanged;
bool blendSrcRgbChanged;
bool blendSrcAlphaChanged;
bool blendDstRgbChanged;
bool blendDstAlphaChanged;
bool blendEqationRgbChanged;
bool blendEqationAlphaChanged;
bool colorMaskChanged;
bool depthTestChanged;
bool depthMaskChanged;
bool stencilTestChanged;
bool cullingEnabledChanged;
bool cullingChanged;
bool windingOrderChanged;
bool sampler7Changed;
bool vboChanged;
bool iboChanged;
bool vaoChanged;
std::vector<bool> vertexAttribArrayChanged;
std::vector<bool> vertexAttribPointerChanged;
void setUiState(Api api);
void checkStateChanged(const GLState& currentGlState);
void checkStateChanged(const GLStateTracker& stateTracker);
void restoreState(const GLState& currentGlState, Api api);
GLStateTracker()
: activeProgramChanged(GL_FALSE), activeTextureUnitChanged(GL_FALSE), boundTextureChanged(GL_FALSE), blendEnabledChanged(GL_FALSE), blendSrcRgbChanged(GL_FALSE),
blendDstRgbChanged(GL_FALSE), blendDstAlphaChanged(GL_FALSE), blendEqationRgbChanged(GL_FALSE), blendEqationAlphaChanged(GL_FALSE), colorMaskChanged(GL_FALSE),
depthTestChanged(GL_FALSE), depthMaskChanged(GL_FALSE), stencilTestChanged(GL_FALSE), cullingEnabledChanged(GL_FALSE), cullingChanged(GL_FALSE),
windingOrderChanged(GL_FALSE), sampler7Changed(GL_FALSE), vboChanged(GL_FALSE), iboChanged(GL_FALSE), vaoChanged(GL_FALSE), vertexAttribArrayChanged(8, GL_FALSE),
vertexAttribPointerChanged(8, GL_FALSE)
{}
};
class UIRenderer
{
public:
struct ProgramData
{
enum Uniform
{
UniformMVPmtx,
UniformFontTexture,
UniformColor,
UniformAlphaMode,
UniformUVmtx,
NumUniform
};
enum Attribute
{
AttributeVertex,
AttributeUV,
NumAttribute
};
int32_t uniforms[NumUniform];
};
const GLuint& getFontIbo()
{
if (!_fontIboCreated)
{
// create the FontIBO
std::vector<uint16_t> fontFaces;
fontFaces.resize(impl::Font_::FontElement);
for (uint32_t i = 0; i < impl::Font_::MaxRenderableLetters; ++i)
{
fontFaces[i * 6u] = static_cast<uint16_t>(0u + i * 4u);
fontFaces[i * 6u + 1u] = static_cast<uint16_t>(3u + i * 4u);
fontFaces[i * 6u + 2u] = static_cast<uint16_t>(1u + i * 4u);
fontFaces[i * 6u + 3u] = static_cast<uint16_t>(3u + i * 4u);
fontFaces[i * 6u + 4u] = static_cast<uint16_t>(0u + i * 4u);
fontFaces[i * 6u + 5u] = static_cast<uint16_t>(2u + i * 4u);
}
GLint binding;
gl::GetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &binding);
gl::GenBuffers(1, &_fontIbo);
gl::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _fontIbo);
gl::BufferData(GL_ELEMENT_ARRAY_BUFFER, static_cast<uint32_t>(sizeof(fontFaces[0]) * fontFaces.size()), &fontFaces[0], GL_STATIC_DRAW);
gl::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, binding);
_uiStateTracker.ibo = _fontIbo;
_fontIboCreated = true;
}
return _fontIbo;
}
const GLuint& getImageVbo()
{
if (!_imageVboCreated)
{
// create the image vbo
const float verts[] = {
/* Position */
-1.f, 1.f, 0.f, 1.0f, 0.0f, 1.0f, // upper left
-1.f, -1.f, 0.f, 1.0f, 0.f, 0.0f, // lower left
1.f, 1.f, 0.f, 1.0f, 1.f, 1.f, // upper right
-1.f, -1.f, 0.f, 1.0f, 0.f, 0.0f, // lower left
1.f, -1.f, 0.f, 1.0f, 1.f, 0.0f, // lower right
1.f, 1.f, 0.f, 1.0f, 1.f, 1.f, // upper right
};
GLint binding;
gl::GetIntegerv(GL_ARRAY_BUFFER_BINDING, &binding);
gl::GenBuffers(1, &_imageVbo);
gl::BindBuffer(GL_ARRAY_BUFFER, _imageVbo);
gl::BufferData(GL_ARRAY_BUFFER, static_cast<uint32_t>(sizeof(verts)), static_cast<const void*>(verts), GL_STATIC_DRAW);
gl::BindBuffer(GL_ARRAY_BUFFER, binding);
_uiStateTracker.vbo = _imageVbo;
_imageVboCreated = true;
}
return _imageVbo;
}
UIRenderer() : _screenRotation(.0f), _program(0), _fontIboCreated(false), _imageVboCreated(false), _samplerBilinear(0), _samplerTrilinear(0), _fontIbo(-1), _imageVbo(-1) {}
UIRenderer(UIRenderer&& rhs)
: _program(std::move(rhs._program)), _programData(std::move(rhs._programData)), _defaultFont(std::move(rhs._defaultFont)), _sdkLogo(std::move(rhs._sdkLogo)),
_defaultTitle(std::move(rhs._defaultTitle)), _defaultDescription(std::move(rhs._defaultDescription)), _defaultControls(std::move(rhs._defaultControls)),
_samplerBilinear(std::move(rhs._samplerBilinear)), _samplerTrilinear(std::move(rhs._samplerTrilinear)), _fontIbo(std::move(rhs._fontIbo)),
_imageVbo(std::move(rhs._imageVbo)), _screenDimensions(std::move(rhs._screenDimensions)), _screenRotation(std::move(rhs._screenRotation)),
_groupId(std::move(rhs._groupId)), _sprites(std::move(rhs._sprites)), _textElements(std::move(rhs._textElements)), _fonts(std::move(rhs._fonts)),
_fontIboCreated(std::move(rhs._fontIboCreated)), _imageVboCreated(std::move(rhs._imageVboCreated))
{
_program = std::move(rhs._program);
rhs._program = 0;
updateResourceOwnership();
}
UIRenderer& operator=(UIRenderer&& rhs)
{
if (this == &rhs) { return *this; }
_program = std::move(rhs._program);
rhs._program = 0;
_programData = std::move(rhs._programData);
_defaultFont = std::move(rhs._defaultFont);
_sdkLogo = std::move(rhs._sdkLogo);
_defaultTitle = std::move(rhs._defaultTitle);
_defaultDescription = std::move(rhs._defaultDescription);
_defaultControls = std::move(rhs._defaultControls);
_samplerBilinear = std::move(rhs._samplerBilinear);
_samplerTrilinear = std::move(rhs._samplerTrilinear);
_fontIbo = std::move(rhs._fontIbo);
_imageVbo = std::move(rhs._imageVbo);
_screenDimensions = std::move(rhs._screenDimensions);
_screenRotation = std::move(rhs._screenRotation);
_groupId = std::move(rhs._groupId);
_fontIboCreated = std::move(rhs._fontIboCreated);
_imageVboCreated = std::move(rhs._imageVboCreated);
updateResourceOwnership();
return *this;
}
UIRenderer& operator=(const UIRenderer& rhs) = delete;
UIRenderer(UIRenderer& rhs) = delete;
~UIRenderer() { release(); }
const ProgramData& getProgramData() { return _programData; }
void init(uint32_t width, uint32_t height, bool fullscreen, bool isFrameBufferSRGB);
void release()
{
_defaultFont.reset();
_defaultTitle.reset();
_defaultDescription.reset();
_defaultControls.reset();
_sdkLogo.reset();
_sprites.clear();
_fonts.clear();
_textElements.clear();
if (_fontIboCreated && _fontIbo != static_cast<uint32_t>(-1)) { gl::DeleteBuffers(1, &_fontIbo); }
if (_imageVboCreated && _imageVbo != static_cast<uint32_t>(-1)) { gl::DeleteBuffers(1, &_imageVbo); }
#if !SC_ENABLED
if (_api != Api::OpenGLES2)
{
if (_samplerBilinear) { gl::DeleteSamplers(1, &_samplerBilinear); }
if (_samplerTrilinear) { gl::DeleteSamplers(1, &_samplerTrilinear); }
}
#endif
_screenRotation = .0f;
_program = 0;
_fontIboCreated = false;
_imageVboCreated = false;
_samplerBilinear = static_cast<GLuint>(0);
_samplerTrilinear = static_cast<GLuint>(0);
_fontIbo = static_cast<GLuint>(-1);
_imageVbo = static_cast<GLuint>(-1);
}
TextElement createTextElement(const std::string& text = "") { return createTextElement(text, _defaultFont); }
TextElement createTextElement(const std::string& text, const Font& font);
TextElement createTextElement(const Font& font) { return createTextElement(std::string(""), font); }
TextElement createTextElement(const std::wstring& text) { return createTextElement(text, _defaultFont); }
TextElement createTextElement(const std::wstring& text, const Font& font);
Text createText(const TextElement& textElement);
Text createText(const std::string& text = "") { return createText(createTextElement(text)); }
Text createText(const std::string& text, const Font& font) { return createText(createTextElement(text, font)); }
Text createText(const Font& font) { return createText(createTextElement(font)); }
Text createText(const std::wstring& text) { return createText(createTextElement(text)); }
Text createText(const std::wstring& text, const Font& font) { return createText(createTextElement(text, font)); }
float getRenderingDimX() const { return _screenDimensions.x; }
float getRenderingDimY() const { return _screenDimensions.y; }
glm::vec2 getRenderingDim() const { return _screenDimensions; }
Rectanglei getViewport() const { return Rectanglei(0, 0, static_cast<int32_t>(getRenderingDimX()), static_cast<int32_t>(getRenderingDimY())); }
void setRenderingDimX(float value) { _screenDimensions.x = value; }
void setRenderingDimY(float value) { _screenDimensions.y = value; }
Font createFont(GLuint texture, const TextureHeader& textureHeader, GLuint sampler = 0);
Font createFont(const Texture& texture, GLuint sampler = 0);
Image createImage(GLuint texture, int32_t width, int32_t height, bool useMipmaps, GLuint sampler = 0);
Image createImage(const Texture& texture, GLuint sampler = 0);
Image createImageFromAtlas(GLuint texture, const Rectanglef& uv, uint32_t width, uint32_t height, bool useMipmaps = false, GLuint sampler = 0);
MatrixGroup createMatrixGroup();
PixelGroup createPixelGroup();
void beginRendering()
{
storeCurrentGlState();
checkStateChanged();
setUiState();
}
void beginRendering(const GLStateTracker& stateTracker)
{
checkStateChanged(stateTracker);
setUiState();
}
void endRendering()
{
checkStateChanged();
restoreState();
}
void endRendering(GLStateTracker& stateTracker) { stateTracker = _uiStateTracker; }
const Font& getDefaultFont() const { return _defaultFont; }
Font& getDefaultFont() { return _defaultFont; }
const Image& getSdkLogo() const { return _sdkLogo; }
Image& getSdkLogo() { return _sdkLogo; }
const Text& getDefaultTitle() const { return _defaultTitle; }
Text& getDefaultTitle() { return _defaultTitle; }
const Text& getDefaultDescription() const { return _defaultDescription; }
Text& getDefaultDescription() { return _defaultDescription; }
const Text& getDefaultControls() const { return _defaultControls; }
Text& getDefaultControls() { return _defaultControls; }
glm::mat4 getProjection() const { return pvr::math::ortho(Api::OpenGLES2, 0.0, getRenderingDimX(), 0.0f, getRenderingDimY()); }
void rotateScreen90degreeCCW()
{
_screenRotation += glm::pi<float>() * .5f;
std::swap(_screenDimensions.x, _screenDimensions.y);
}
void rotateScreen90degreeCW()
{
_screenRotation -= glm::pi<float>() * .5f;
std::swap(_screenDimensions.x, _screenDimensions.y);
}
glm::mat4 getScreenRotation() const { return glm::rotate(_screenRotation, glm::vec3(0.0f, 0.0f, 1.f)); }
GLStateTracker getStateTracker() const { return _uiStateTracker; }
Api getApiVersion() { return _api; }
private:
void storeCurrentGlState();
void setUiState();
void checkStateChanged();
void checkStateChanged(const GLStateTracker& stateTracker);
void restoreState();
void updateResourceOwnership()
{
std::for_each(_sprites.begin(), _sprites.end(), [this](SpriteWeakRef& sprite) { sprite.lock()->setUIRenderer(this); });
std::for_each(_fonts.begin(), _fonts.end(), [this](FontWeakRef& font) { font.lock()->setUIRenderer(this); });
std::for_each(_textElements.begin(), _textElements.end(), [this](TextElementWeakRef& textElement) { textElement.lock()->setUIRenderer(this); });
}
friend class ::pvr::ui::impl::Image_;
friend class ::pvr::ui::impl::Text_;
friend class ::pvr::ui::impl::Group_;
friend class ::pvr::ui::impl::Sprite_;
friend class ::pvr::ui::impl::Font_;
friend class ::pvr::ui::impl::TextElement_;
friend class ::pvr::ui::impl::MatrixGroup_;
uint64_t generateGroupId() { return _groupId++; }
GLuint getSamplerBilinear() const { return _samplerBilinear; }
GLuint getSamplerTrilinear() const { return _samplerTrilinear; }
void init_CreateDefaultFont();
void init_CreateDefaultSampler();
void init_CreateDefaultSdkLogo();
void init_CreateDefaultTitle();
void init_CreateShaders(bool framebufferSRGB);
std::vector<SpriteWeakRef> _sprites;
std::vector<TextElementWeakRef> _textElements;
std::vector<FontWeakRef> _fonts;
ProgramData _programData;
Font _defaultFont;
Image _sdkLogo;
Text _defaultTitle;
Text _defaultDescription;
Text _defaultControls;
GLuint _program;
GLuint _samplerBilinear;
GLuint _samplerTrilinear;
GLuint _fontIbo;
bool _fontIboCreated;
GLuint _imageVbo;
bool _imageVboCreated;
glm::vec2 _screenDimensions;
float _screenRotation;
uint64_t _groupId = 1;
GLStateTracker _uiStateTracker;
GLState _currentState;
Api _api;
};
} // namespace ui
} // namespace pvr