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

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