source: trunk/src/gl/gl_context.cc @ 38

Last change on this file since 38 was 37, checked in by epyon, 12 years ago
  • gl_context added
  • removed geometry shader support from gl_program (non-GL 2.1/GLES 2.0 compatible)
  • cleaned up warnings
File size: 9.8 KB
Line 
1// Copyright (C) 2012-2013 Kornel Kisielewicz
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4
5#include "nv/gl/gl_context.hh"
6
7#include "nv/gl/gl_enum.hh"
8#include "nv/lib/gl.hh"
9
10using namespace nv;
11
12void gl_context::clear( const clear_state& cs )
13{
14        // apply_framebuffer
15        apply_scissor_test( cs.scissor_test );
16        apply_color_mask( cs.color_mask );
17        apply_depth_mask( cs.depth_mask );
18        // stencil_mask_separate
19
20        if ( m_clear_color != cs.color )
21        {
22                glClearColor( cs.color.r, cs.color.g, cs.color.b, cs.color.a );
23                m_clear_color = cs.color;
24        }
25
26        if ( m_clear_depth != cs.depth )
27        {
28                glClearDepth( cs.depth );
29                m_clear_depth = cs.depth;
30        }
31
32        if ( m_clear_stencil != cs.stencil )
33        {
34                glClearStencil( cs.stencil );
35                m_clear_stencil = cs.stencil;
36        }
37
38        glClear( cs.buffers );
39}
40
41const ivec4& gl_context::get_viewport()
42{
43        return m_viewport;
44}
45
46void gl_context::set_viewport( const ivec4& viewport )
47{
48        if ( viewport.z < 0 || viewport.w < 0 )
49        {
50                throw new logic_error("viewport width and height must be greater than zero!");
51        }
52
53        m_viewport = viewport;
54        glViewport( viewport.x, viewport.y, viewport.z, viewport.w );
55}
56
57void gl_context::enable( unsigned int what, bool value )
58{
59        if ( value )
60        {
61                glEnable( what );
62        }
63        else
64        {
65                glDisable( what );
66        }
67}
68
69void gl_context::apply_stencil_test( const stencil_test& stencil )
70{
71        if ( m_render_state.stencil_test.enabled != stencil.enabled )
72        {
73                enable( GL_STENCIL_TEST, stencil.enabled );
74                m_render_state.stencil_test.enabled = stencil.enabled;
75        }
76
77        if ( stencil.enabled )
78        {
79                apply_stencil_face( GL_FRONT, m_render_state.stencil_test.front_face, stencil.front_face );
80                apply_stencil_face( GL_BACK,  m_render_state.stencil_test.back_face,  stencil.back_face );
81        }
82}
83
84void gl_context::apply_stencil_face( int face, stencil_test_face& stencil, const stencil_test_face& new_stencil )
85{
86        if (( stencil.op_fail       != new_stencil.op_fail       ) ||
87                ( stencil.op_depth_fail != new_stencil.op_depth_fail ) ||
88                ( stencil.op_depth_pass != new_stencil.op_depth_pass ) )
89        {
90                glStencilOpSeparate( face,
91                        stencil_operation_to_enum( new_stencil.op_fail ),
92                        stencil_operation_to_enum( new_stencil.op_depth_fail ),
93                        stencil_operation_to_enum( new_stencil.op_depth_pass )
94                );
95
96                stencil.op_fail       = new_stencil.op_fail;
97                stencil.op_depth_fail = new_stencil.op_depth_fail;
98                stencil.op_depth_pass = new_stencil.op_depth_pass;
99        }
100
101        if (( stencil.function  != new_stencil.function ) ||
102                ( stencil.ref_value != new_stencil.ref_value ) ||
103                ( stencil.mask      != new_stencil.mask ))
104        {
105                glStencilFuncSeparate( face,
106                        stencil_function_to_enum( new_stencil.function ),
107                        new_stencil.ref_value,
108                        new_stencil.mask
109                );
110
111                stencil.function  = new_stencil.function;
112                stencil.ref_value = new_stencil.ref_value;
113                stencil.mask      = new_stencil.mask;
114        }
115}
116
117void gl_context::apply_scissor_test( const scissor_test& scissor )
118{
119        if ( m_render_state.scissor_test.enabled != scissor.enabled )
120        {
121                enable( GL_SCISSOR_TEST, scissor.enabled );
122                m_render_state.scissor_test.enabled = scissor.enabled;
123        }
124
125        if ( scissor.dim.x < 0 || scissor.dim.y < 0 )
126        {
127                throw new logic_error("scissor_test.rect width and height must be greater than zero!");
128        }
129
130        if ( scissor.enabled )
131        {
132                if ( m_render_state.scissor_test.dim != scissor.dim || m_render_state.scissor_test.pos != scissor.pos )
133                {
134                        glScissor(
135                                scissor.pos.x, scissor.pos.y,
136                                scissor.dim.x, scissor.dim.y
137                        );
138                        m_render_state.scissor_test.dim = scissor.dim;
139                        m_render_state.scissor_test.pos = scissor.pos;
140                }
141        }
142}
143
144void gl_context::apply_depth_test( const depth_test& depth )
145{
146        if ( m_render_state.depth_test.enabled != depth.enabled )
147        {
148                enable( GL_DEPTH_TEST, depth.enabled );
149                m_render_state.depth_test.enabled = depth.enabled;
150        }
151
152        if ( depth.enabled )
153        {
154                if ( m_render_state.depth_test.function != depth.function )
155                {
156                        glDepthFunc( depth_state_function_to_enum( depth.function ) );
157                        m_render_state.depth_test.function = depth.function;
158                }
159        }
160}
161
162void gl_context::apply_depth_mask( bool mask )
163{
164        if ( m_render_state.depth_mask != mask )
165        {
166                glDepthMask( mask );
167                m_render_state.depth_mask = mask;
168        }
169}
170
171void gl_context::apply_depth_range( const depth_range& range )
172{
173        if ( range.near < 0.0 || range.near > 1.0 )
174        {
175                throw new logic_error("render_state.depth_range.near must be between zero and one!");
176        }
177        if ( range.far < 0.0 || range.far > 1.0 )
178        {
179                throw new logic_error("render_state.depth_range.far must be between zero and one!");
180        }
181
182        if ((m_render_state.depth_range.far  != range.far) ||
183                (m_render_state.depth_range.near != range.near))
184        {
185                glDepthRange( range.near, range.far );
186
187                m_render_state.depth_range.far  = range.far;
188                m_render_state.depth_range.near = range.near;
189        }
190}
191
192void gl_context::apply_color_mask( const color_mask& mask )
193{
194        if ( m_render_state.color_mask != mask )
195        {
196                glColorMask( mask.red, mask.green, mask.blue, mask.alpha );
197                m_render_state.color_mask = mask;
198        }
199}
200
201void gl_context::apply_blending( const blending& blend )
202{
203        if ( m_render_state.blending.enabled != blend.enabled )
204        {
205                enable( GL_BLEND, blend.enabled );
206                m_render_state.blending.enabled = blend.enabled;
207        }
208
209        if ( blend.enabled )
210        {
211                if ((m_render_state.blending.src_rgb_factor   != blend.src_rgb_factor ) ||
212                        (m_render_state.blending.dst_rgb_factor   != blend.dst_rgb_factor ) ||
213                        (m_render_state.blending.src_alpha_factor != blend.src_alpha_factor ) ||
214                        (m_render_state.blending.dst_alpha_factor != blend.dst_alpha_factor ))
215                {
216                        glBlendFuncSeparate(
217                                blending_factor_to_enum( blend.src_rgb_factor ),
218                                blending_factor_to_enum( blend.dst_rgb_factor ),
219                                blending_factor_to_enum( blend.src_alpha_factor ),
220                                blending_factor_to_enum( blend.dst_alpha_factor )
221                        );
222
223                        m_render_state.blending.src_rgb_factor   = blend.src_rgb_factor;
224                        m_render_state.blending.dst_rgb_factor   = blend.dst_rgb_factor;
225                        m_render_state.blending.src_alpha_factor = blend.src_alpha_factor;
226                        m_render_state.blending.dst_alpha_factor = blend.dst_alpha_factor;
227                }
228
229                if ((m_render_state.blending.rgb_equation   != blend.rgb_equation ) ||
230                        (m_render_state.blending.alpha_equation != blend.alpha_equation ))
231                {
232                        glBlendEquationSeparate(
233                                blending_equation_to_enum( blend.rgb_equation ),
234                                blending_equation_to_enum( blend.alpha_equation )
235                        );
236
237                        m_render_state.blending.rgb_equation   = blend.rgb_equation;
238                        m_render_state.blending.alpha_equation = blend.alpha_equation;
239                }
240
241                if (( m_render_state.blending.color != blend.color ))
242                {
243                        glBlendColor( blend.color.r, blend.color.g, blend.color.b, blend.color.a );
244                        m_render_state.blending.color = blend.color;
245                }
246        }
247}
248
249
250void gl_context::apply_culling( const culling& cull )
251{
252        if ( m_render_state.culling.enabled != cull.enabled )
253        {
254                enable( GL_CULL_FACE, cull.enabled );
255                m_render_state.culling.enabled = cull.enabled;
256        }
257
258        if ( cull.enabled )
259        {
260                if ( m_render_state.culling.face != cull.face )
261                {
262                        glCullFace( culling_face_type_to_enum(cull.face) );
263                        m_render_state.culling.face = cull.face;
264                }
265
266                if ( m_render_state.culling.order != cull.order )
267                {
268                        glFrontFace( culling_order_type_to_enum( cull.order ) );
269                        m_render_state.culling.order = cull.order;
270                }
271        }
272}
273
274
275void gl_context::force_apply_render_state( const render_state& state )
276{
277        enable( GL_CULL_FACE, state.culling.enabled );
278        glCullFace( culling_face_type_to_enum( state.culling.face ) );
279        glFrontFace( culling_order_type_to_enum( state.culling.order ) );
280
281        enable( GL_SCISSOR_TEST, state.scissor_test.enabled );
282        glScissor(
283                state.scissor_test.pos.x, state.scissor_test.pos.y,
284                state.scissor_test.dim.x, state.scissor_test.dim.y
285        );
286
287        enable( GL_STENCIL_TEST, state.stencil_test.enabled );
288        force_apply_stencil_face( GL_FRONT, state.stencil_test.front_face );
289        force_apply_stencil_face( GL_BACK,  state.stencil_test.back_face  );
290
291        enable( GL_DEPTH_TEST, state.depth_test.enabled );
292        glDepthFunc( depth_state_function_to_enum( state.depth_test.function ) );
293        glDepthRange( state.depth_range.near, state.depth_range.far );
294
295        enable( GL_BLEND, state.blending.enabled );
296        glBlendFuncSeparate(
297                blending_factor_to_enum( state.blending.src_rgb_factor ),
298                blending_factor_to_enum( state.blending.dst_rgb_factor ),
299                blending_factor_to_enum( state.blending.src_alpha_factor ),
300                blending_factor_to_enum( state.blending.dst_alpha_factor )
301        );
302        glBlendEquationSeparate(
303                blending_equation_to_enum( state.blending.rgb_equation ),
304                blending_equation_to_enum( state.blending.alpha_equation )
305        );
306        glBlendColor(
307                state.blending.color.r, state.blending.color.g,
308                state.blending.color.b, state.blending.color.a
309        );
310
311        glDepthMask( state.depth_mask );
312        glColorMask(
313                state.color_mask.red, state.color_mask.green,
314                state.color_mask.blue, state.color_mask.alpha
315        );
316}
317
318void gl_context::force_apply_stencil_face( int face, const stencil_test_face& stencil )
319{
320        glStencilOpSeparate( face,
321                stencil_operation_to_enum( stencil.op_fail ),
322                stencil_operation_to_enum( stencil.op_depth_fail ),
323                stencil_operation_to_enum( stencil.op_depth_pass )
324        );
325
326        glStencilFuncSeparate( face,
327                stencil_function_to_enum( stencil.function ),
328                stencil.ref_value,
329                stencil.mask
330        );
331}
332
333
334void gl_context::apply_render_state( const render_state& state )
335{
336        // apply_primitive_restart
337        apply_culling( state.culling );
338        // apply_program_point_size
339        // apply_rasterization_mode
340        apply_scissor_test( state.scissor_test );
341        apply_stencil_test( state.stencil_test );
342        apply_depth_test( state.depth_test );
343        apply_depth_range( state.depth_range );
344        apply_blending( state.blending );
345        apply_color_mask( state.color_mask );
346        apply_depth_mask( state.depth_mask );
347}
348
Note: See TracBrowser for help on using the repository browser.