1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "GLcommon/ScopedGLState.h"
17 
18 #include "GLcommon/GLEScontext.h"
19 
20 #include <GLES/gl.h>
21 #include <GLES2/gl2.h>
22 #include <GLES2/gl2ext.h>
23 #include <GLES3/gl31.h>
24 
25 #include <unordered_map>
26 
push(GLenum name)27 void ScopedGLState::push(GLenum name) {
28     auto& gl = GLEScontext::dispatcher();
29 
30     StateVector v;
31 
32     switch (name) {
33     case GL_DRAW_FRAMEBUFFER_BINDING:
34     case GL_READ_FRAMEBUFFER_BINDING:
35     case GL_CURRENT_PROGRAM:
36     case GL_VERTEX_ARRAY_BINDING:
37     case GL_ARRAY_BUFFER_BINDING:
38     case GL_TEXTURE_BINDING_2D:
39     case GL_TEXTURE_BINDING_CUBE_MAP:
40     case GL_VIEWPORT:
41     case GL_COLOR_WRITEMASK:
42         gl.glGetIntegerv(name, v.intData);
43         break;
44     case GL_DEPTH_RANGE:
45         gl.glGetFloatv(name, v.floatData);
46         break;
47     // glIsEnabled queries
48     case GL_BLEND:
49     case GL_SCISSOR_TEST:
50     case GL_DEPTH_TEST:
51     case GL_STENCIL_TEST:
52     case GL_CULL_FACE:
53     case GL_RASTERIZER_DISCARD:
54     case GL_SAMPLE_ALPHA_TO_COVERAGE:
55     case GL_SAMPLE_COVERAGE:
56     case GL_POLYGON_OFFSET_FILL:
57         v.intData[0] = gl.glIsEnabled(name);
58         break;
59     default:
60         fprintf(stderr,
61                 "%s: ScopedGLState doesn't support 0x%x yet, it's mainly for "
62                 "texture emulation by drawing fullscreen quads.\n", __func__,
63                 name);
64         break;
65     }
66 
67     mStateMap[name] = v;
68 }
69 
push(std::initializer_list<GLenum> names)70 void ScopedGLState::push(std::initializer_list<GLenum> names) {
71     for (const auto name : names) {
72         push(name);
73     }
74 }
75 
pushForCoreProfileTextureEmulation()76 void ScopedGLState::pushForCoreProfileTextureEmulation() {
77     push({ GL_DRAW_FRAMEBUFFER_BINDING,
78            GL_READ_FRAMEBUFFER_BINDING,
79            GL_VERTEX_ARRAY_BINDING,
80            GL_CURRENT_PROGRAM,
81            GL_VIEWPORT,
82            GL_SCISSOR_TEST,
83            GL_DEPTH_TEST,
84            GL_BLEND,
85            GL_DEPTH_RANGE,
86            GL_COLOR_WRITEMASK,
87            GL_SAMPLE_ALPHA_TO_COVERAGE,
88            GL_SAMPLE_COVERAGE,
89            GL_CULL_FACE,
90            GL_POLYGON_OFFSET_FILL,
91            GL_RASTERIZER_DISCARD,
92            GL_TEXTURE_BINDING_2D });
93 }
94 
~ScopedGLState()95 ScopedGLState::~ScopedGLState() {
96     auto& gl = GLEScontext::dispatcher();
97 
98     for (const auto& it : mStateMap) {
99         GLenum name = it.first;
100         const StateVector& v = it.second;
101         switch (name) {
102             case GL_DRAW_FRAMEBUFFER_BINDING:
103                 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, v.intData[0]);
104             case GL_READ_FRAMEBUFFER_BINDING:
105                 gl.glBindFramebuffer(GL_READ_FRAMEBUFFER, v.intData[0]);
106                 break;
107             case GL_CURRENT_PROGRAM:
108                 gl.glUseProgram(v.intData[0]);
109                 break;
110             case GL_VERTEX_ARRAY_BINDING:
111                 gl.glBindVertexArray(v.intData[0]);
112                 break;
113             case GL_ARRAY_BUFFER_BINDING:
114                 gl.glBindBuffer(GL_ARRAY_BUFFER, v.intData[0]);
115                 break;
116             case GL_TEXTURE_BINDING_2D:
117                 gl.glBindTexture(GL_TEXTURE_2D, v.intData[0]);
118                 break;
119             case GL_TEXTURE_BINDING_CUBE_MAP:
120                 gl.glBindTexture(GL_TEXTURE_CUBE_MAP, v.intData[0]);
121                 break;
122             case GL_VIEWPORT:
123                 gl.glViewport(v.intData[0], v.intData[1], v.intData[2], v.intData[3]);
124                 break;
125             case GL_COLOR_WRITEMASK:
126                 gl.glColorMask(v.intData[0], v.intData[1], v.intData[2], v.intData[3]);
127                 break;
128             case GL_DEPTH_RANGE:
129                 gl.glDepthRange(v.floatData[0], v.floatData[1]);
130                 break;
131                 // glIsEnabled queries
132             case GL_BLEND:
133             case GL_SCISSOR_TEST:
134             case GL_DEPTH_TEST:
135             case GL_STENCIL_TEST:
136             case GL_CULL_FACE:
137             case GL_RASTERIZER_DISCARD:
138             case GL_SAMPLE_ALPHA_TO_COVERAGE:
139             case GL_SAMPLE_COVERAGE:
140             case GL_POLYGON_OFFSET_FILL:
141                 if (v.intData[0]) {
142                     gl.glEnable(name);
143                 } else {
144                     gl.glDisable(name);
145                 }
146                 break;
147             default:
148                 fprintf(stderr,
149                         "%s: ScopedGLState doesn't support 0x%x yet, it's mainly for "
150                         "texture emulation by drawing fullscreen quads.\n", __func__,
151                         name);
152                 break;
153         }
154     }
155 }
156