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

Last change on this file since 398 was 398, checked in by epyon, 10 years ago
  • cleanup of glm usage
File size: 22.6 KB
Line 
1// Copyright (C) 2012-2015 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/gl/gl_context.hh"
8
9#include "nv/gl/gl_enum.hh"
10#include "nv/lib/gl.hh"
11#include "nv/gl/gl_device.hh"
12#include "nv/core/logger.hh"
13
14using namespace nv;
15
16nv::vertex_array nv::gl_context::create_vertex_array()
17{
18        vertex_array result = m_vertex_arrays.create();
19        vertex_array_info* info = m_vertex_arrays.get( result );
20        info->count       = 0;
21        info->index       = buffer();
22        info->index_owner = false;
23        info->index_type  = USHORT;
24        return result;
25}
26
27nv::framebuffer nv::gl_context::create_framebuffer()
28{
29        if ( is_gl_extension_loaded( GL_EXT_FRAMEBUFFER_OBJECT ) && is_gl_extension_loaded( GL_EXT_FRAMEBUFFER_BLIT ) )
30        {
31                unsigned glid   = 0;
32                glGenFramebuffers( 1, &glid );
33                framebuffer result = m_framebuffers.create();
34                gl_framebuffer_info* info = m_framebuffers.get( result );
35                info->glid = glid;
36                info->depth_rb_glid = 0;
37                info->color_attachment_count = 0;
38                return result;
39        }
40        else return framebuffer();
41}
42
43void nv::gl_context::release( vertex_array va )
44{
45        vertex_array_info* info = m_vertex_arrays.get( va );
46        if ( info )
47        {
48                for ( uint32 i = 0; i < info->count; ++i )
49                {
50                        if ( info->attr[i].owner ) m_device->release( info->attr[i].vbuffer );
51                }
52                if ( info->index.is_valid() && info->index_owner) m_device->release( info->index );
53                m_vertex_arrays.destroy( va );
54        }
55}
56
57void nv::gl_context::release( framebuffer f )
58{
59        gl_framebuffer_info* info = m_framebuffers.get( f );
60        if ( info )
61        {
62                // TODO: release textures?
63                glBindFramebuffer( GL_FRAMEBUFFER, 0 );
64                glBindRenderbuffer( GL_RENDERBUFFER, 0 );
65                if ( info->depth_rb_glid == 0 )
66                        glDeleteRenderbuffers( 1, &info->depth_rb_glid );
67                glDeleteFramebuffers( 1, &info->glid );
68                m_framebuffers.destroy( f );
69        }
70}
71
72const vertex_array_info* nv::gl_context::get_vertex_array_info( vertex_array va ) const
73{
74        return m_vertex_arrays.get( va );
75}
76
77const framebuffer_info* nv::gl_context::get_framebuffer_info( framebuffer f ) const
78{
79        return m_framebuffers.get( f );
80}
81
82vertex_array_info* nv::gl_context::get_vertex_array_info_mutable( vertex_array va )
83{
84        return m_vertex_arrays.get( va );
85}
86
87void nv::gl_context::attach( framebuffer f, output_slot slot, texture t )
88{
89        // TODO: framebuffer variable, so no re-binding?
90        // TODO: support 1d, 3d textures, cubemaps or layers?
91        // TODO: support GL_READ_FRAMEBUFFER?
92        const gl_framebuffer_info* info  = m_framebuffers.get( f );
93        const gl_texture_info*     tinfo = (gl_texture_info*)m_device->get_texture_info( t );
94        if ( info )
95        {
96                glBindFramebuffer( GL_FRAMEBUFFER, info->glid );
97                unsigned gl_type = texture_type_to_enum( tinfo->type );
98
99                if ( tinfo )
100                {
101                        //              if ( tinfo->size.y == 0 )
102                                //                      glFramebufferTexture1D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+(unsigned)slot, GL_TEXTURE_1D, tinfo->glid, 0 );
103                        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+(unsigned)slot, gl_type, tinfo->glid, 0 );
104                }
105                else
106                {
107                        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+(unsigned)slot, gl_type, 0, 0 );
108                }
109
110        }
111}
112
113void nv::gl_context::attach( framebuffer f, texture depth )
114{
115        // TODO: framebuffer variable, so no re-binding?
116        // TODO: support GL_READ_FRAMEBUFFER?
117        const gl_framebuffer_info* info  = m_framebuffers.get( f );
118        const gl_texture_info*     tinfo = (gl_texture_info*)m_device->get_texture_info( depth );
119        if ( info )
120        {
121                glBindFramebuffer( GL_FRAMEBUFFER, info->glid );
122                unsigned gl_type = texture_type_to_enum( tinfo->type );
123
124                if ( tinfo )
125                {
126                        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, gl_type, tinfo->glid, 0 );
127                }
128                else
129                {
130                        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, gl_type, 0, 0 );
131                }
132        }
133}
134
135void nv::gl_context::attach( framebuffer f, ivec2 size )
136{
137        // TODO: framebuffer variable, so no re-binding?
138        // TODO: support GL_READ_FRAMEBUFFER?
139        gl_framebuffer_info* info  = m_framebuffers.get( f );
140        if ( info )
141        {
142                glBindFramebuffer( GL_FRAMEBUFFER, info->glid );
143                if ( info->depth_rb_glid ) glDeleteRenderbuffers( 1, &(info->depth_rb_glid) );
144                glGenRenderbuffers( 1, &(info->depth_rb_glid) );
145                glBindRenderbuffer( GL_RENDERBUFFER, info->depth_rb_glid );
146                glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.x, size.y );
147                glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, info->depth_rb_glid );
148                glBindRenderbuffer( GL_RENDERBUFFER, 0 );
149        }
150
151}
152
153void nv::gl_context::blit( framebuffer f, clear_state::buffers_type mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )
154{
155        gl_framebuffer_info* info  = m_framebuffers.get( f );
156        if ( info )
157        {
158                glBindFramebuffer( GL_FRAMEBUFFER, info->glid );
159                unsigned filter = mask == clear_state::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;
160                glBlitFramebuffer( src1.x, src1.y, src2.x, src2.y, dst1.x, dst1.y, dst2.x, dst2.y, clear_state_buffers_to_mask( mask ), filter );
161        }
162}
163
164
165bool nv::gl_context::check( framebuffer_slot ft )
166{
167        if ( is_gl_extension_loaded( GL_EXT_FRAMEBUFFER_OBJECT ) && is_gl_extension_loaded( GL_EXT_FRAMEBUFFER_BLIT ) )
168        {
169                unsigned result = glCheckFramebufferStatus( framebuffer_slot_to_enum(ft) );
170                if ( result == GL_FRAMEBUFFER_COMPLETE ) return true;
171                switch ( result )
172                {
173                case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT         : NV_LOG_ERROR( "gl_context::check : Framebuffer incomplete attachment!" ); break;
174                case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT : NV_LOG_ERROR( "gl_context::check : Framebuffer missing attachment!" ); break;
175                case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS         : NV_LOG_ERROR( "gl_context::check : Framebuffer incomplete dimensions!" ); break;
176                case GL_FRAMEBUFFER_INCOMPLETE_FORMATS            : NV_LOG_ERROR( "gl_context::check : Framebuffer incomplete formats!" ); break;
177                case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER        : NV_LOG_ERROR( "gl_context::check : Framebuffer incomplete draw buffer!" ); break;
178                case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER        : NV_LOG_ERROR( "gl_context::check : Framebuffer incomplete read buffer!" ); break;
179                case GL_FRAMEBUFFER_UNSUPPORTED                   : NV_LOG_ERROR( "gl_context::check : Framebuffer format combination unsupported!" ); break;
180                default: NV_LOG_ERROR( "gl_context::check : Unknown Framebuffer error! (", result, ")" ); break;
181                }
182        }
183        else
184        {
185                NV_LOG_ERROR( "gl_context::check : Framebuffer extensions not loaded!" );
186        }
187        return false;
188}
189
190void nv::gl_context::bind( framebuffer f, framebuffer_slot ft /*= FRAMEBUFFER_BOTH */ )
191{
192        const gl_framebuffer_info* info = m_framebuffers.get( f );
193        if ( info )
194        {
195                glBindFramebuffer( framebuffer_slot_to_enum(ft), info->glid );
196        }
197        else
198        {
199                glBindFramebuffer( framebuffer_slot_to_enum(ft), 0 );
200        }
201}
202
203void gl_context::bind( texture t, texture_slot slot )
204{
205        const gl_texture_info* info = static_cast< const gl_texture_info* >( m_device->get_texture_info( t ) );
206        if ( info )
207        {
208                glActiveTexture( GL_TEXTURE0 + static_cast< GLenum >( slot ) );
209                glBindTexture( texture_type_to_enum( info->type ), info->glid );
210        }
211}
212
213void nv::gl_context::bind( program p )
214{
215        gl_program_info* info = ((gl_device*)m_device)->m_programs.get( p );
216        if ( info )
217        {
218                glUseProgram( info->glid );
219                ((gl_device*)m_device)->update_uniforms( info );
220        }
221}
222
223// void nv::gl_context::bind( buffer b )
224// {
225//      const gl_buffer_info* info = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( b ) );
226//      if ( info )
227//      {
228//              glBindBuffer( buffer_type_to_enum( info->type ), info->glid );
229//      }
230// }
231
232void nv::gl_context::bind( vertex_array va )
233{
234        const vertex_array_info* info = m_vertex_arrays.get( va );
235        if ( info )
236        {
237                for ( uint32 i = 0; i < info->count; ++i )
238                {
239                        const vertex_buffer_attribute& vba = info->attr[i];
240                        uint32 location                    = static_cast<uint32>( vba.location );
241                        glEnableVertexAttribArray( location );
242                        const gl_buffer_info* vinfo = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( vba.vbuffer ) );
243                        if ( vinfo && vinfo->type == VERTEX_BUFFER )
244                                glBindBuffer( GL_ARRAY_BUFFER, vinfo->glid );
245                        else
246                        {
247                                // TODO: report error
248                        }
249
250                        glVertexAttribPointer(
251                                location,
252                                static_cast<GLint>( vba.components ),
253                                nv::datatype_to_gl_enum( vba.dtype ),
254                                GL_FALSE,
255                                static_cast<GLsizei>( vba.stride ),
256                                (void*)vba.offset
257                                );
258                }
259                glBindBuffer( GL_ARRAY_BUFFER, 0 );
260
261                if ( info->index.is_valid() )
262                {
263                        const gl_buffer_info* iinfo = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( info->index ) );
264                        if ( iinfo && iinfo->type == INDEX_BUFFER )
265                        {
266                                glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, iinfo->glid );
267                        }
268                        else
269                        {
270                                // TODO: report error
271                        }
272                }
273        }
274}
275
276void nv::gl_context::unbind( program )
277{
278        glUseProgram( 0 );
279}
280
281// void nv::gl_context::unbind( buffer b )
282// {
283//      const gl_buffer_info* info = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( b ) );
284//      if ( info )
285//      {
286//              glBindBuffer( buffer_type_to_enum( info->type ), 0 );
287//      }
288// }
289
290void nv::gl_context::unbind( vertex_array va )
291{
292        const vertex_array_info* info = m_vertex_arrays.get( va );
293        if ( info )
294        {
295                if ( info->index.is_valid() )
296                {
297                        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
298                }
299
300                for ( uint32 i = 0; i < info->count; ++i )
301                {
302                        glDisableVertexAttribArray( static_cast<uint32>( info->attr[i].location ) );
303                }
304        }
305}
306
307void nv::gl_context::unbind( framebuffer f )
308{
309        // this way we are sure that the extension is loaded
310        const gl_framebuffer_info* info = m_framebuffers.get( f );
311        if ( info )
312        {
313                glBindFramebuffer( GL_FRAMEBUFFER, 0 );
314        }
315        glDrawBuffer( GL_BACK );
316        glReadBuffer( GL_BACK );
317}
318
319void nv::gl_context::update( texture t, void* data )
320{
321        const gl_texture_info* info = static_cast< const gl_texture_info* >( m_device->get_texture_info( t ) );
322        if ( info )
323        {
324                image_format format  = info->format;
325                ivec2        size    = info->size;
326                unsigned     gl_type = texture_type_to_enum( info->type );
327
328                glBindTexture( gl_type, info->glid );
329                glTexImage2D( gl_type, 0, (GLint)nv::image_format_to_internal_enum(format.format), size.x, size.y, 0, nv::image_format_to_enum(format.format), nv::datatype_to_gl_enum(format.type), data );
330        }
331}
332
333void gl_context::update( buffer b, const void* data, nv::size_t offset, nv::size_t size )
334{
335        const gl_buffer_info* info = static_cast< const gl_buffer_info* >( m_device->get_buffer_info( b ) );
336        if ( info )
337        {
338                GLenum glenum = buffer_type_to_enum( info->type );
339                glBindBuffer( glenum, info->glid );
340                glBufferSubData( glenum, (GLintptr)offset, (GLsizeiptr)size, data );
341        }
342}
343
344void gl_context::clear( const clear_state& cs )
345{
346        // apply_framebuffer
347       
348        apply_scissor_test( cs.scissor_test );
349        apply_color_mask( cs.color_mask );
350        apply_depth_mask( cs.depth_mask );
351        // stencil_mask_separate
352
353        if ( m_clear_color != cs.color )
354        {
355                glClearColor( cs.color.r, cs.color.g, cs.color.b, cs.color.a );
356                m_clear_color = cs.color;
357        }
358
359        if ( m_clear_depth != cs.depth )
360        {
361                glClearDepth( cs.depth );
362                m_clear_depth = cs.depth;
363        }
364
365        if ( m_clear_stencil != cs.stencil )
366        {
367                glClearStencil( cs.stencil );
368                m_clear_stencil = cs.stencil;
369        }
370       
371        glClear( clear_state_buffers_to_mask( cs.buffers ) );
372}
373
374const ivec4& gl_context::get_viewport()
375{
376        return m_viewport;
377}
378
379void gl_context::set_viewport( const ivec4& viewport )
380{
381        if ( viewport.z < 0 || viewport.w < 0 )
382        {
383                NV_THROW( logic_error, "viewport width and height must be greater than zero!");
384        }
385
386        m_viewport = viewport;
387        glViewport( viewport.x, viewport.y, viewport.z, viewport.w );
388}
389
390void gl_context::enable( unsigned int what, bool value )
391{
392        if ( value )
393        {
394                glEnable( what );
395        }
396        else
397        {
398                glDisable( what );
399        }
400}
401
402void gl_context::apply_stencil_test( const stencil_test& stencil )
403{
404        if ( m_render_state.stencil_test.enabled != stencil.enabled )
405        {
406                enable( GL_STENCIL_TEST, stencil.enabled );
407                m_render_state.stencil_test.enabled = stencil.enabled;
408        }
409       
410        if ( stencil.enabled )
411        {
412                apply_stencil_face( GL_FRONT, m_render_state.stencil_test.front_face, stencil.front_face );
413                apply_stencil_face( GL_BACK,  m_render_state.stencil_test.back_face,  stencil.back_face );
414        }
415}
416
417void gl_context::apply_stencil_face( unsigned face, stencil_test_face& stencil, const stencil_test_face& new_stencil )
418{
419        if (( stencil.op_fail       != new_stencil.op_fail       ) ||
420                ( stencil.op_depth_fail != new_stencil.op_depth_fail ) ||
421                ( stencil.op_depth_pass != new_stencil.op_depth_pass ) )
422        {
423                glStencilOpSeparate( face,
424                        stencil_operation_to_enum( new_stencil.op_fail ),
425                        stencil_operation_to_enum( new_stencil.op_depth_fail ),
426                        stencil_operation_to_enum( new_stencil.op_depth_pass )
427                );
428
429                stencil.op_fail       = new_stencil.op_fail;
430                stencil.op_depth_fail = new_stencil.op_depth_fail;
431                stencil.op_depth_pass = new_stencil.op_depth_pass;
432        }
433
434        if (( stencil.function  != new_stencil.function ) ||
435                ( stencil.ref_value != new_stencil.ref_value ) ||
436                ( stencil.mask      != new_stencil.mask ))
437        {
438                glStencilFuncSeparate( face,
439                        stencil_function_to_enum( new_stencil.function ),
440                        new_stencil.ref_value,
441                        new_stencil.mask
442                );
443
444                stencil.function  = new_stencil.function;
445                stencil.ref_value = new_stencil.ref_value;
446                stencil.mask      = new_stencil.mask;
447        }
448}
449
450void gl_context::apply_scissor_test( const scissor_test& scissor )
451{
452        if ( m_render_state.scissor_test.enabled != scissor.enabled )
453        {
454                enable( GL_SCISSOR_TEST, scissor.enabled );
455                m_render_state.scissor_test.enabled = scissor.enabled;
456        }
457
458        if ( scissor.dim.x < 0 || scissor.dim.y < 0 )
459        {
460                NV_THROW( logic_error, "scissor_test.rect width and height must be greater than zero!" );
461        }
462
463        if ( scissor.enabled )
464        {
465                if ( m_render_state.scissor_test.dim != scissor.dim || m_render_state.scissor_test.pos != scissor.pos )
466                {
467                        glScissor(
468                                scissor.pos.x, scissor.pos.y,
469                                scissor.dim.x, scissor.dim.y
470                        );
471                        m_render_state.scissor_test.dim = scissor.dim;
472                        m_render_state.scissor_test.pos = scissor.pos;
473                }
474        }
475}
476
477void gl_context::apply_depth_test( const depth_test& depth )
478{
479        if ( m_render_state.depth_test.enabled != depth.enabled )
480        {
481                enable( GL_DEPTH_TEST, depth.enabled );
482                m_render_state.depth_test.enabled = depth.enabled;
483        }
484
485        if ( depth.enabled )
486        {
487                if ( m_render_state.depth_test.function != depth.function )
488                {
489                        glDepthFunc( depth_state_function_to_enum( depth.function ) );
490                        m_render_state.depth_test.function = depth.function;
491                }
492        }
493}
494
495void gl_context::apply_depth_mask( bool mask )
496{
497        if ( m_render_state.depth_mask != mask )
498        {
499                glDepthMask( mask );
500                m_render_state.depth_mask = mask;
501        }
502}
503
504void gl_context::apply_polygon_mode( const polygon_mode& mode )
505{
506        if ( m_render_state.polygon_mode.fill != mode.fill )
507        {
508                glPolygonMode( GL_FRONT_AND_BACK, polygon_mode_fill_to_enum( mode.fill ) );
509                m_render_state.polygon_mode.fill = mode.fill;
510        }
511}
512
513
514void gl_context::apply_depth_range( const depth_range& range )
515{
516        if ( range.near < 0.0 || range.near > 1.0 )
517        {
518                NV_THROW( logic_error, "render_state.depth_range.near must be between zero and one!");
519        }
520        if ( range.far < 0.0 || range.far > 1.0 )
521        {
522                NV_THROW( logic_error, "render_state.depth_range.far must be between zero and one!");
523        }
524
525        if ((m_render_state.depth_range.far  != range.far) ||
526                (m_render_state.depth_range.near != range.near))
527        {
528                glDepthRange( range.near, range.far );
529
530                m_render_state.depth_range.far  = range.far;
531                m_render_state.depth_range.near = range.near;
532        }
533}
534
535void gl_context::apply_color_mask( const color_mask& mask )
536{
537        if ( m_render_state.color_mask != mask )
538        {
539                glColorMask( mask.red, mask.green, mask.blue, mask.alpha );
540                m_render_state.color_mask = mask;
541        }
542}
543
544void gl_context::apply_blending( const blending& blend )
545{
546        if ( m_render_state.blending.enabled != blend.enabled )
547        {
548                enable( GL_BLEND, blend.enabled );
549                m_render_state.blending.enabled = blend.enabled;
550        }
551
552        if ( blend.enabled )
553        {
554                if ((m_render_state.blending.src_rgb_factor   != blend.src_rgb_factor ) ||
555                        (m_render_state.blending.dst_rgb_factor   != blend.dst_rgb_factor ) ||
556                        (m_render_state.blending.src_alpha_factor != blend.src_alpha_factor ) ||
557                        (m_render_state.blending.dst_alpha_factor != blend.dst_alpha_factor ))
558                {
559                        glBlendFuncSeparate(
560                                blending_factor_to_enum( blend.src_rgb_factor ),
561                                blending_factor_to_enum( blend.dst_rgb_factor ),
562                                blending_factor_to_enum( blend.src_alpha_factor ),
563                                blending_factor_to_enum( blend.dst_alpha_factor )
564                        );
565
566                        m_render_state.blending.src_rgb_factor   = blend.src_rgb_factor;
567                        m_render_state.blending.dst_rgb_factor   = blend.dst_rgb_factor;
568                        m_render_state.blending.src_alpha_factor = blend.src_alpha_factor;
569                        m_render_state.blending.dst_alpha_factor = blend.dst_alpha_factor;
570                }
571
572                if ((m_render_state.blending.rgb_equation   != blend.rgb_equation ) ||
573                        (m_render_state.blending.alpha_equation != blend.alpha_equation ))
574                {
575                        glBlendEquationSeparate(
576                                blending_equation_to_enum( blend.rgb_equation ),
577                                blending_equation_to_enum( blend.alpha_equation )
578                        );
579
580                        m_render_state.blending.rgb_equation   = blend.rgb_equation;
581                        m_render_state.blending.alpha_equation = blend.alpha_equation;
582                }
583
584                if (( m_render_state.blending.color != blend.color ))
585                {
586                        glBlendColor( blend.color.r, blend.color.g, blend.color.b, blend.color.a );
587                        m_render_state.blending.color = blend.color;
588                }
589        }
590}
591
592
593void gl_context::apply_culling( const culling& cull )
594{
595        if ( m_render_state.culling.enabled != cull.enabled )
596        {
597                enable( GL_CULL_FACE, cull.enabled );
598                m_render_state.culling.enabled = cull.enabled;
599        }
600
601        if ( cull.enabled )
602        {
603                if ( m_render_state.culling.face != cull.face )
604                {
605                        glCullFace( culling_face_type_to_enum(cull.face) );
606                        m_render_state.culling.face = cull.face;
607                }
608
609                if ( m_render_state.culling.order != cull.order )
610                {
611                        glFrontFace( culling_order_type_to_enum( cull.order ) );
612                        m_render_state.culling.order = cull.order;
613                }
614        }
615}
616
617
618void gl_context::force_apply_render_state( const render_state& state )
619{
620        enable( GL_CULL_FACE, state.culling.enabled );
621        glCullFace( culling_face_type_to_enum( state.culling.face ) );
622        glFrontFace( culling_order_type_to_enum( state.culling.order ) );
623
624        enable( GL_SCISSOR_TEST, state.scissor_test.enabled );
625        glScissor(
626                state.scissor_test.pos.x, state.scissor_test.pos.y,
627                state.scissor_test.dim.x, state.scissor_test.dim.y
628        );
629
630        enable( GL_STENCIL_TEST, state.stencil_test.enabled );
631        force_apply_stencil_face( GL_FRONT, state.stencil_test.front_face );
632        force_apply_stencil_face( GL_BACK,  state.stencil_test.back_face  );
633
634        enable( GL_DEPTH_TEST, state.depth_test.enabled );
635        glDepthFunc( depth_state_function_to_enum( state.depth_test.function ) );
636        glDepthRange( state.depth_range.near, state.depth_range.far );
637
638        enable( GL_BLEND, state.blending.enabled );
639        glBlendFuncSeparate(
640                blending_factor_to_enum( state.blending.src_rgb_factor ),
641                blending_factor_to_enum( state.blending.dst_rgb_factor ),
642                blending_factor_to_enum( state.blending.src_alpha_factor ),
643                blending_factor_to_enum( state.blending.dst_alpha_factor )
644        );
645        glBlendEquationSeparate(
646                blending_equation_to_enum( state.blending.rgb_equation ),
647                blending_equation_to_enum( state.blending.alpha_equation )
648        );
649        glBlendColor(
650                state.blending.color.r, state.blending.color.g,
651                state.blending.color.b, state.blending.color.a
652        );
653
654        glDepthMask( state.depth_mask );
655        glColorMask(
656                state.color_mask.red, state.color_mask.green,
657                state.color_mask.blue, state.color_mask.alpha
658        );
659        glPolygonMode( GL_FRONT_AND_BACK, polygon_mode_fill_to_enum( state.polygon_mode.fill ) );
660}
661
662void gl_context::force_apply_stencil_face( unsigned face, const stencil_test_face& stencil )
663{
664        glStencilOpSeparate( face,
665                stencil_operation_to_enum( stencil.op_fail ),
666                stencil_operation_to_enum( stencil.op_depth_fail ),
667                stencil_operation_to_enum( stencil.op_depth_pass )
668        );
669
670        glStencilFuncSeparate( face,
671                stencil_function_to_enum( stencil.function ),
672                stencil.ref_value,
673                stencil.mask
674        );
675}
676
677
678void gl_context::apply_render_state( const render_state& state )
679{
680        // apply_primitive_restart
681        apply_culling( state.culling );
682        // apply_program_point_size
683        // apply_rasterization_mode
684        apply_scissor_test( state.scissor_test );
685        apply_stencil_test( state.stencil_test );
686        apply_depth_test( state.depth_test );
687        apply_depth_range( state.depth_range );
688        apply_blending( state.blending );
689        apply_color_mask( state.color_mask );
690        apply_depth_mask( state.depth_mask );
691        apply_polygon_mode( state.polygon_mode );
692}
693
694
695gl_context::gl_context( device* a_device, void* a_handle )
696        : context( a_device ), m_handle( a_handle )
697{
698        // TODO: configurable:
699        load_gl_extensions( GL_EXT_FRAMEBUFFER_BLIT | GL_EXT_FRAMEBUFFER_OBJECT );
700        force_apply_render_state( m_render_state );
701}
702
703
704nv::gl_context::~gl_context()
705{
706        while ( m_framebuffers.size() > 0 )
707                release( m_framebuffers.get_handle(0) );
708        while ( m_vertex_arrays.size() > 0 )
709                release( m_vertex_arrays.get_handle(0) );
710}
711
712void nv::gl_context::apply_engine_uniforms( program p, const scene_state& s )
713{
714        gl_program_info* info = ((gl_device*)m_device)->m_programs.get( p );
715        if ( info )
716        {
717                for ( auto& u : *info->m_engine_uniforms )
718                {
719                        u->set( this, &s );
720                }
721        }
722}
723
724void nv::gl_context::set_draw_buffers( uint32 count, const output_slot* slots )
725{
726        if ( count == 0 ) return;
727        if ( count == 1 )
728        {
729                set_draw_buffer( slots[0] );
730                return;
731        }
732        unsigned int buffers[8];
733        count = nv::min<uint32>( count, 8 );
734        for ( uint32 i = 0; i < count; ++i )
735        {
736                buffers[i] = output_slot_to_enum( slots[i] );
737                if ( slots[i] > OUTPUT_7 ) buffers[i] = 0;
738        }
739        glDrawBuffers( (GLsizei)count, buffers );
740}
741
742void nv::gl_context::set_draw_buffer( output_slot slot )
743{
744        glDrawBuffer( output_slot_to_enum(slot) );
745}
746
747void nv::gl_context::set_read_buffer( output_slot slot )
748{
749        glReadBuffer( output_slot_to_enum(slot) );
750}
751
752void gl_context::draw( primitive prim, const render_state& rs, program p, vertex_array va, nv::size_t count )
753{
754        apply_render_state( rs );
755        const vertex_array_info* info = m_vertex_arrays.get( va );
756        if ( count > 0 && info )
757        {
758                bind( p );
759                bind( va );
760                if ( info->index.is_valid() )
761                {
762                        glDrawElements( primitive_to_enum(prim), static_cast<GLsizei>( count ), datatype_to_gl_enum( info->index_type ), 0 );
763                }
764                else
765                {
766                        glDrawArrays( primitive_to_enum(prim), 0, static_cast<GLsizei>( count ) );
767                }
768                unbind( va );
769                //unbind( p );
770        }
771}
Note: See TracBrowser for help on using the repository browser.