// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gl/scoped_binders.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_state_restorer.h" namespace gl { ScopedFramebufferBinder::ScopedFramebufferBinder(unsigned int fbo) : state_restorer_(!GLContext::GetCurrent() ? nullptr : GLContext::GetCurrent()->GetGLStateRestorer()), old_fbo_(-1) { if (!state_restorer_) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo_); glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); } ScopedFramebufferBinder::~ScopedFramebufferBinder() { if (state_restorer_) { DCHECK(!!GLContext::GetCurrent()); DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer()); state_restorer_->RestoreFramebufferBindings(); } else { glBindFramebufferEXT(GL_FRAMEBUFFER, old_fbo_); } } ScopedActiveTexture::ScopedActiveTexture(unsigned int texture) : state_restorer_(!GLContext::GetCurrent() ? nullptr : GLContext::GetCurrent()->GetGLStateRestorer()), old_texture_(-1) { if (!state_restorer_) glGetIntegerv(GL_ACTIVE_TEXTURE, &old_texture_); glActiveTexture(texture); } ScopedActiveTexture::~ScopedActiveTexture() { if (state_restorer_) { DCHECK(!!GLContext::GetCurrent()); DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer()); state_restorer_->RestoreActiveTexture(); } else { glActiveTexture(old_texture_); } } ScopedTextureBinder::ScopedTextureBinder(unsigned int target, unsigned int id) : state_restorer_(!GLContext::GetCurrent() ? nullptr : GLContext::GetCurrent()->GetGLStateRestorer()), target_(target), old_id_(-1) { if (!state_restorer_) { GLenum target_getter = 0; switch (target) { case GL_TEXTURE_2D: target_getter = GL_TEXTURE_BINDING_2D; break; case GL_TEXTURE_CUBE_MAP: target_getter = GL_TEXTURE_BINDING_CUBE_MAP; break; case GL_TEXTURE_EXTERNAL_OES: target_getter = GL_TEXTURE_BINDING_EXTERNAL_OES; break; case GL_TEXTURE_RECTANGLE_ARB: target_getter = GL_TEXTURE_BINDING_RECTANGLE_ARB; break; default: NOTIMPLEMENTED() << " Target not supported."; } glGetIntegerv(target_getter, &old_id_); } glBindTexture(target_, id); } ScopedTextureBinder::~ScopedTextureBinder() { if (state_restorer_) { DCHECK(!!GLContext::GetCurrent()); DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer()); state_restorer_->RestoreActiveTextureUnitBinding(target_); } else { glBindTexture(target_, old_id_); } } ScopedUseProgram::ScopedUseProgram(unsigned int program) : state_restorer_(!GLContext::GetCurrent() ? nullptr : GLContext::GetCurrent()->GetGLStateRestorer()), old_program_(-1) { if (!state_restorer_) glGetIntegerv(GL_CURRENT_PROGRAM, &old_program_); glUseProgram(program); } ScopedUseProgram::~ScopedUseProgram() { if (state_restorer_) { DCHECK(!!GLContext::GetCurrent()); DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer()); state_restorer_->RestoreProgramBindings(); } else { glUseProgram(old_program_); } } ScopedVertexAttribArray::ScopedVertexAttribArray(unsigned int index, int size, unsigned int type, char normalized, int stride, const void* pointer) : state_restorer_(!GLContext::GetCurrent() ? nullptr : GLContext::GetCurrent()->GetGLStateRestorer()), buffer_(0), enabled_(GL_FALSE), index_(index), size_(-1), type_(-1), normalized_(GL_FALSE), stride_(0), pointer_(nullptr) { if (!state_restorer_) { glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled_); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size_); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type_); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized_); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride_); glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pointer_); } glEnableVertexAttribArray(index); glVertexAttribPointer(index, size, type, normalized, stride, pointer); } ScopedVertexAttribArray::~ScopedVertexAttribArray() { if (state_restorer_) { DCHECK(!!GLContext::GetCurrent()); DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer()); state_restorer_->RestoreVertexAttribArray(index_); } else { ScopedBufferBinder buffer_binder(GL_ARRAY_BUFFER, buffer_); glVertexAttribPointer(index_, size_, type_, normalized_, stride_, pointer_); if (enabled_ == GL_FALSE) glDisableVertexAttribArray(index_); } } ScopedBufferBinder::ScopedBufferBinder(unsigned int target, unsigned int id) : state_restorer_(!GLContext::GetCurrent() ? nullptr : GLContext::GetCurrent()->GetGLStateRestorer()), target_(target), old_id_(-1) { if (!state_restorer_) { GLenum target_getter = 0; switch (target) { case GL_ARRAY_BUFFER: target_getter = GL_ARRAY_BUFFER_BINDING; break; case GL_PIXEL_UNPACK_BUFFER: target_getter = GL_PIXEL_UNPACK_BUFFER_BINDING; break; default: NOTIMPLEMENTED() << " Target not supported."; } glGetIntegerv(target_getter, &old_id_); } glBindBuffer(target_, id); } ScopedBufferBinder::~ScopedBufferBinder() { if (state_restorer_) { DCHECK(!!GLContext::GetCurrent()); DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer()); state_restorer_->RestoreBufferBinding(target_); } else { glBindBuffer(target_, old_id_); } } ScopedViewport::ScopedViewport(int x, int y, int width, int height) { glGetIntegerv(GL_VIEWPORT, data_); glViewport(x, y, width, height); } ScopedViewport::~ScopedViewport() { glViewport(data_[0], data_[1], data_[2], data_[3]); } ScopedColorMask::ScopedColorMask(char red, char green, char blue, char alpha) { glGetBooleanv(GL_COLOR_WRITEMASK, colors_); glColorMask(red, green, blue, alpha); } ScopedColorMask::~ScopedColorMask() { glColorMask(colors_[0], colors_[1], colors_[2], colors_[3]); } ScopedCapability::ScopedCapability(unsigned capability, unsigned char enabled) : capability_(capability) { enabled_ = glIsEnabled(capability_); if (enabled == GL_TRUE) { glEnable(capability); } else { glDisable(capability); } } ScopedCapability::~ScopedCapability() { if (enabled_ == GL_TRUE) { glEnable(capability_); } else { glDisable(capability_); } } } // namespace gl