1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/gl/scoped_binders.h"
6 #include "ui/gl/gl_bindings.h"
7 #include "ui/gl/gl_context.h"
8 #include "ui/gl/gl_state_restorer.h"
9 
10 namespace gl {
11 
ScopedFramebufferBinder(unsigned int fbo)12 ScopedFramebufferBinder::ScopedFramebufferBinder(unsigned int fbo)
13     : state_restorer_(!GLContext::GetCurrent()
14                           ? nullptr
15                           : GLContext::GetCurrent()->GetGLStateRestorer()),
16       old_fbo_(-1) {
17   if (!state_restorer_)
18     glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo_);
19   glBindFramebufferEXT(GL_FRAMEBUFFER, fbo);
20 }
21 
~ScopedFramebufferBinder()22 ScopedFramebufferBinder::~ScopedFramebufferBinder() {
23   if (state_restorer_) {
24     DCHECK(!!GLContext::GetCurrent());
25     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
26     state_restorer_->RestoreFramebufferBindings();
27   } else {
28     glBindFramebufferEXT(GL_FRAMEBUFFER, old_fbo_);
29   }
30 }
31 
ScopedActiveTexture(unsigned int texture)32 ScopedActiveTexture::ScopedActiveTexture(unsigned int texture)
33     : state_restorer_(!GLContext::GetCurrent()
34                           ? nullptr
35                           : GLContext::GetCurrent()->GetGLStateRestorer()),
36       old_texture_(-1) {
37   if (!state_restorer_)
38     glGetIntegerv(GL_ACTIVE_TEXTURE, &old_texture_);
39   glActiveTexture(texture);
40 }
41 
~ScopedActiveTexture()42 ScopedActiveTexture::~ScopedActiveTexture() {
43   if (state_restorer_) {
44     DCHECK(!!GLContext::GetCurrent());
45     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
46     state_restorer_->RestoreActiveTexture();
47   } else {
48     glActiveTexture(old_texture_);
49   }
50 }
51 
ScopedTextureBinder(unsigned int target,unsigned int id)52 ScopedTextureBinder::ScopedTextureBinder(unsigned int target, unsigned int id)
53     : state_restorer_(!GLContext::GetCurrent()
54                           ? nullptr
55                           : GLContext::GetCurrent()->GetGLStateRestorer()),
56       target_(target),
57       old_id_(-1) {
58   if (!state_restorer_) {
59     GLenum target_getter = 0;
60     switch (target) {
61       case GL_TEXTURE_2D:
62         target_getter = GL_TEXTURE_BINDING_2D;
63         break;
64       case GL_TEXTURE_CUBE_MAP:
65         target_getter = GL_TEXTURE_BINDING_CUBE_MAP;
66         break;
67       case GL_TEXTURE_EXTERNAL_OES:
68         target_getter = GL_TEXTURE_BINDING_EXTERNAL_OES;
69         break;
70       case GL_TEXTURE_RECTANGLE_ARB:
71         target_getter = GL_TEXTURE_BINDING_RECTANGLE_ARB;
72         break;
73       default:
74         NOTIMPLEMENTED() << " Target not supported.";
75     }
76     glGetIntegerv(target_getter, &old_id_);
77   }
78   glBindTexture(target_, id);
79 }
80 
~ScopedTextureBinder()81 ScopedTextureBinder::~ScopedTextureBinder() {
82   if (state_restorer_) {
83     DCHECK(!!GLContext::GetCurrent());
84     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
85     state_restorer_->RestoreActiveTextureUnitBinding(target_);
86   } else {
87     glBindTexture(target_, old_id_);
88   }
89 }
90 
ScopedUseProgram(unsigned int program)91 ScopedUseProgram::ScopedUseProgram(unsigned int program)
92     : state_restorer_(!GLContext::GetCurrent()
93                           ? nullptr
94                           : GLContext::GetCurrent()->GetGLStateRestorer()),
95       old_program_(-1) {
96   if (!state_restorer_)
97     glGetIntegerv(GL_CURRENT_PROGRAM, &old_program_);
98   glUseProgram(program);
99 }
100 
~ScopedUseProgram()101 ScopedUseProgram::~ScopedUseProgram() {
102   if (state_restorer_) {
103     DCHECK(!!GLContext::GetCurrent());
104     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
105     state_restorer_->RestoreProgramBindings();
106   } else {
107     glUseProgram(old_program_);
108   }
109 }
110 
ScopedVertexAttribArray(unsigned int index,int size,unsigned int type,char normalized,int stride,const void * pointer)111 ScopedVertexAttribArray::ScopedVertexAttribArray(unsigned int index,
112                                                  int size,
113                                                  unsigned int type,
114                                                  char normalized,
115                                                  int stride,
116                                                  const void* pointer)
117     : state_restorer_(!GLContext::GetCurrent()
118                           ? nullptr
119                           : GLContext::GetCurrent()->GetGLStateRestorer()),
120       buffer_(0),
121       enabled_(GL_FALSE),
122       index_(index),
123       size_(-1),
124       type_(-1),
125       normalized_(GL_FALSE),
126       stride_(0),
127       pointer_(nullptr) {
128   if (!state_restorer_) {
129     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_);
130     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled_);
131     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size_);
132     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type_);
133     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized_);
134     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride_);
135     glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &pointer_);
136   }
137 
138   glEnableVertexAttribArray(index);
139   glVertexAttribPointer(index, size, type, normalized, stride, pointer);
140 }
141 
~ScopedVertexAttribArray()142 ScopedVertexAttribArray::~ScopedVertexAttribArray() {
143   if (state_restorer_) {
144     DCHECK(!!GLContext::GetCurrent());
145     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
146     state_restorer_->RestoreVertexAttribArray(index_);
147   } else {
148     ScopedBufferBinder buffer_binder(GL_ARRAY_BUFFER, buffer_);
149     glVertexAttribPointer(index_, size_, type_, normalized_, stride_, pointer_);
150     if (enabled_ == GL_FALSE)
151       glDisableVertexAttribArray(index_);
152   }
153 }
154 
ScopedBufferBinder(unsigned int target,unsigned int id)155 ScopedBufferBinder::ScopedBufferBinder(unsigned int target, unsigned int id)
156     : state_restorer_(!GLContext::GetCurrent()
157                           ? nullptr
158                           : GLContext::GetCurrent()->GetGLStateRestorer()),
159       target_(target),
160       old_id_(-1) {
161   if (!state_restorer_) {
162     GLenum target_getter = 0;
163     switch (target) {
164       case GL_ARRAY_BUFFER:
165         target_getter = GL_ARRAY_BUFFER_BINDING;
166         break;
167       case GL_PIXEL_UNPACK_BUFFER:
168         target_getter = GL_PIXEL_UNPACK_BUFFER_BINDING;
169         break;
170       default:
171         NOTIMPLEMENTED() << " Target not supported.";
172     }
173     glGetIntegerv(target_getter, &old_id_);
174   }
175   glBindBuffer(target_, id);
176 }
177 
~ScopedBufferBinder()178 ScopedBufferBinder::~ScopedBufferBinder() {
179   if (state_restorer_) {
180     DCHECK(!!GLContext::GetCurrent());
181     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
182     state_restorer_->RestoreBufferBinding(target_);
183   } else {
184     glBindBuffer(target_, old_id_);
185   }
186 }
187 
ScopedViewport(int x,int y,int width,int height)188 ScopedViewport::ScopedViewport(int x, int y, int width, int height) {
189   glGetIntegerv(GL_VIEWPORT, data_);
190   glViewport(x, y, width, height);
191 }
192 
~ScopedViewport()193 ScopedViewport::~ScopedViewport() {
194   glViewport(data_[0], data_[1], data_[2], data_[3]);
195 }
196 
ScopedColorMask(char red,char green,char blue,char alpha)197 ScopedColorMask::ScopedColorMask(char red, char green, char blue, char alpha) {
198   glGetBooleanv(GL_COLOR_WRITEMASK, colors_);
199   glColorMask(red, green, blue, alpha);
200 }
201 
~ScopedColorMask()202 ScopedColorMask::~ScopedColorMask() {
203   glColorMask(colors_[0], colors_[1], colors_[2], colors_[3]);
204 }
205 
ScopedCapability(unsigned capability,unsigned char enabled)206 ScopedCapability::ScopedCapability(unsigned capability, unsigned char enabled)
207     : capability_(capability) {
208   enabled_ = glIsEnabled(capability_);
209   if (enabled == GL_TRUE) {
210     glEnable(capability);
211   } else {
212     glDisable(capability);
213   }
214 }
215 
~ScopedCapability()216 ScopedCapability::~ScopedCapability() {
217   if (enabled_ == GL_TRUE) {
218     glEnable(capability_);
219   } else {
220     glDisable(capability_);
221   }
222 }
223 
224 }  // namespace gl
225