1 /** @file glstate.h  GL state.
2  *
3  * GL state management is abstracted inside this class to retain plausible
4  * independence from OpenGL as the underlying rendering API. Also, Direct3D
5  * uses object-based state management.
6  *
7  * @authors Copyright (c) 2013-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
8  *
9  * @par License
10  * LGPL: http://www.gnu.org/licenses/lgpl.html
11  *
12  * <small>This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Lesser General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or (at your
15  * option) any later version. This program is distributed in the hope that it
16  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
18  * General Public License for more details. You should have received a copy of
19  * the GNU Lesser General Public License along with this program; if not, see:
20  * http://www.gnu.org/licenses</small>
21  */
22 
23 #ifndef LIBGUI_GLSTATE_H
24 #define LIBGUI_GLSTATE_H
25 
26 #include <de/libcore.h>
27 #include <de/Rectangle>
28 #include <utility>
29 
30 #include "../GLInfo"
31 
32 namespace de {
33 
34 class GLFramebuffer;
35 
36 namespace gl /// OpenGL constants, flags, and other definitions.
37 {
38     enum ColorMaskFlag {
39         WriteNone  = 0,
40         WriteRed   = 0x1,
41         WriteGreen = 0x2,
42         WriteBlue  = 0x4,
43         WriteAlpha = 0x8,
44         WriteAll   = WriteRed | WriteGreen | WriteBlue | WriteAlpha
45     };
46     Q_DECLARE_FLAGS(ColorMask, ColorMaskFlag)
47     Q_DECLARE_OPERATORS_FOR_FLAGS(ColorMask)
48 
49     enum Comparison {
50         Never,
51         Always,
52         Equal,
53         NotEqual,
54         Less,
55         Greater,
56         LessOrEqual,
57         GreaterOrEqual
58     };
59     enum Blend {
60         Zero,
61         One,
62         SrcColor,
63         OneMinusSrcColor,
64         SrcAlpha,
65         OneMinusSrcAlpha,
66         DestColor,
67         OneMinusDestColor,
68         DestAlpha,
69         OneMinusDestAlpha
70     };
71     typedef std::pair<Blend, Blend> BlendFunc;
72     enum BlendOp {
73         Add,
74         Subtract,
75         ReverseSubtract
76     };
77     enum Cull {
78         None,
79         Front,
80         Back
81     };
82 } // namespace gl
83 
84 /**
85  * GL state.
86  *
87  * All manipulation of OpenGL state must occur through this class. If OpenGL
88  * state is changed manually, it will result in GLState not knowing about it,
89  * potentially leading to the incorrect state being in effect later on.
90  *
91  * GLState instances can either be created on demand with GLState::push(), or
92  * one can keep a GLState instance around for repeating use. The stack exists
93  * to aid structured drawing: it is not required to use the stack for all
94  * drawing. GLState::apply() can be called for any GLState instance to use it
95  * as the current GL state.
96  *
97  * @note The default viewport is (0,0)&rarr;(0,0). The viewport has to be set
98  * when the desired size is known (for instance when a Canvas is resized).
99  *
100  * @ingroup gl
101  */
102 class LIBGUI_PUBLIC GLState
103 {
104 public:
105     /**
106      * Constructs a GL state with the default values for all properties.
107      */
108     GLState();
109 
110     GLState(GLState const &other);
111     GLState &operator=(GLState const &other);
112     bool operator==(const GLState &);
113 
114     GLState &setCull(gl::Cull mode);
115     GLState &setDepthTest(bool enable);
116     GLState &setDepthFunc(gl::Comparison func);
117     GLState &setDepthWrite(bool enable);
118     GLState &setAlphaTest(bool enable);
119     GLState &setAlphaLimit(float greaterThanValue);
120     GLState &setBlend(bool enable);
121     GLState &setBlendFunc(gl::Blend src, gl::Blend dest);
122     GLState &setBlendFunc(gl::BlendFunc func);
123     GLState &setBlendOp(gl::BlendOp op);
124     GLState &setColorMask(gl::ColorMask mask);
125     GLState &setTarget(GLFramebuffer &target);
126     GLState &setDefaultTarget();
127     GLState &setViewport(Rectanglei  const &viewportRect);
128     GLState &setViewport(Rectangleui const &viewportRect);
129 
130     /**
131      * Sets a viewport using coordinates that have been normalized within the
132      * current render target. This is useful for operations that should be
133      * independent of target size.
134      *
135      * @param normViewportRect  Normalized viewport rectangle.
136      */
137     GLState &setNormalizedViewport(Rectanglef const &normViewportRect);
138 
139     GLState &setScissor(Rectanglei const &scissorRect);
140     GLState &setScissor(Rectangleui const &scissorRect);
141 
142     /**
143      * Sets a scissor using coordinates that have been normalized within the
144      * current viewport.
145      *
146      * @param normScissorRect  Normalized scissor rectangle.
147      */
148     GLState &setNormalizedScissor(Rectanglef const &normScissorRect);
149 
150     GLState &clearScissor();
151 
152     gl::Cull cull() const;
153     bool depthTest() const;
154     gl::Comparison depthFunc() const;
155     bool depthWrite() const;
156     bool alphaTest() const;
157     float alphaLimit() const;
158     bool blend() const;
159     gl::Blend srcBlendFunc() const;
160     gl::Blend destBlendFunc() const;
161     gl::BlendFunc blendFunc() const;
162     gl::BlendOp blendOp() const;
163     gl::ColorMask colorMask() const;
164     GLFramebuffer &target() const;
165     Rectangleui viewport() const;
166     Rectanglef normalizedViewport() const;
167     bool scissor() const;
168     Rectangleui scissorRect() const;
169 
170     /**
171      * Updates the OpenGL state to match this GLState. Until this is called no
172      * changes occur in the OpenGL state. Calling this more than once is
173      * allowed; the subsequent calls do nothing.
174      *
175      * @todo Remove excess calls to apply() once all direct GL1 state
176      * manipulation has been removed.
177      */
178     void apply() const;
179 
180 public:
181     /**
182      * Tells GLState to consider the native OpenGL state undefined, meaning
183      * that when the next GLState is applied, all properties need to be set
184      * rather than just the changed ones.
185      *
186      * @todo Remove this once all direct OpenGL state changes have been
187      * removed.
188      */
189     static void considerNativeStateUndefined();
190 
191     /**
192      * Returns the current (i.e., topmost) state on the GL state stack.
193      */
194     static GLState &current();
195 
196     /**
197      * Pushes a copy of the current state onto the current thread's GL state
198      * stack.
199      *
200      * @return  Reference to the new state.
201      */
202     static GLState &push();
203 
204     /**
205      * Pops the topmost state off the current thread's stack. Returns a reference
206      * to the state that has now become the new current state.
207      */
208     static GLState &pop();
209 
210     /**
211      * Pushes a state onto the current thread's GL state stack.
212      *
213      * @param state  State to push. Ownership taken.
214      */
215     static void push(GLState *state);
216 
217     /**
218      * Removes the topmost state off of the current thread's stack.
219      *
220      * @return State instance. Ownership given to caller.
221      */
222     static GLState *take();
223 
224     static dsize stackDepth();
225 
226 private:
227     DENG2_PRIVATE(d)
228 };
229 
230 } // namespace de
231 
232 #endif // LIBGUI_GLSTATE_H
233