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

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