source: trunk/nv/interface/device.hh @ 302

Last change on this file since 302 was 302, checked in by epyon, 11 years ago
  • buffers and vertex_arrays are now handle based
File size: 10.3 KB
RevLine 
[32]1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6/**
7 * @file device.hh
8 * @author Kornel Kisielewicz epyon@chaosforge.org
9 * @brief Device class
10 */
11
12#ifndef NV_DEVICE_HH
13#define NV_DEVICE_HH
14
15#include <nv/common.hh>
16#include <nv/string.hh>
[301]17#include <nv/handle.hh>
[238]18#include <nv/interface/mesh_data.hh>
[42]19#include <nv/interface/vertex_buffer.hh>
[90]20#include <nv/interface/image_data.hh>
[32]21
22namespace nv
23{
24        class window;
25        class program;
26
[302]27        struct texture_tag {};
28        struct vertex_array_tag {};
29        struct buffer_tag {};
30        typedef handle< uint32, 16, 16, buffer_tag >       buffer;
31        typedef handle< uint32, 16, 16, texture_tag >      texture;
32        typedef handle< uint32, 16, 16, vertex_array_tag > vertex_array;
33
34
[301]35        struct sampler
36        {
37                enum filter
38                {
39                        LINEAR,
40                        NEAREST,
41                        NEAREST_MIPMAP_NEAREST,
42                        LINEAR_MIPMAP_NEAREST,
43                        NEAREST_MIPMAP_LINEAR,
44                        LINEAR_MIPMAP_LINEAR
45                };
46                enum wrap
47                {
48                        CLAMP_TO_EDGE,
49                        CLAMP_TO_BORDER,
50                        MIRRORED_REPEAT,
51                        REPEAT
52                };
53
54                filter filter_min;
55                filter filter_max;
56                wrap wrap_s;
57                wrap wrap_t;
58
59                sampler() : filter_min( LINEAR ), filter_max( LINEAR ), wrap_s( REPEAT ), wrap_t( REPEAT ) {}
60                sampler( filter min, filter max, wrap s, wrap t )
61                        : filter_min( min ), filter_max( max ), wrap_s( s ), wrap_t( t ) {}
62                sampler( filter f, wrap w )
63                        : filter_min( f ), filter_max( f ), wrap_s( w ), wrap_t( w ) {}
64
65        };
66
[302]67        struct buffer_info
68        {
69                buffer_type type;
70                buffer_hint hint;
71                size_t      size;
72        };
73
74
[301]75        struct texture_info
76        {
77                ivec2        size;
78                image_format format;
79                sampler      sampler;
80        };
81
[302]82        struct vertex_buffer_attribute
83        {
84                buffer   vbuffer;
85                datatype dtype;
86                size_t   components;
87                size_t   offset;
88                size_t   stride;
89                slot     location;
90                bool     owner;
91        };
[301]92
[302]93        struct vertex_array_info
94        {
95                static const int MAX_ATTRIBUTES = 24;
[301]96
[302]97                uint32        count;
98                buffer        index;
99                bool          index_owner;
100                datatype      index_type;
101                vertex_buffer_attribute attr[MAX_ATTRIBUTES];
102        };
103
[32]104        class device
105        {
[302]106                friend class context;
[32]107        public:
[228]108                virtual window* create_window( uint16 width, uint16 height, bool fullscreen ) = 0;
[245]109                virtual window* adopt_window( void* sys_w_handle, void* sys_dc ) = 0;
[39]110                virtual program* create_program( const string& vs_source, const string& fs_source ) = 0;
[302]111                virtual buffer create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source = nullptr ) = 0;
[90]112                virtual image_data* create_image_data( const std::string& filename ) = 0; // temporary
[301]113                virtual texture create_texture( ivec2 size, image_format aformat, sampler asampler, void* data = nullptr ) = 0;
[302]114                virtual void release( texture ) = 0;
115                virtual void release( buffer ) = 0;
[301]116                virtual const texture_info* get_texture_info( texture ) = 0;
[302]117                virtual const buffer_info* get_buffer_info( buffer ) = 0;
[92]118                virtual uint32 get_ticks() = 0;
119                virtual void delay( uint32 ms ) = 0;
[301]120                virtual texture create_texture( image_data* data, sampler asampler )
[292]121                {
[301]122                        return create_texture( data->get_size(), data->get_format(), asampler, (void*)data->get_data() );
[292]123                }
124
[302]125                virtual vertex_array create_vertex_array()
126                {
127                        vertex_array result = m_vertex_arrays.create();
128                        vertex_array_info* info = m_vertex_arrays.get( result );
129                        info->count       = 0;
130                        info->index       = buffer();
131                        info->index_owner = false;
132                        info->index_type  = USHORT;
133                        return result;
134                }
135
136                virtual void release( vertex_array va )
137                {
138                        vertex_array_info* info = m_vertex_arrays.get( va );
139                        if ( info )
140                        {
141                                for ( uint32 i = 0; i < info->count; ++i )
142                                {
143                                        if ( info->attr[i].owner ) release( info->attr[i].vbuffer );
144                                }
145                                if ( info->index.is_valid() && info->index_owner) release( info->index );
146                                m_vertex_arrays.destroy( va );
147                        }
148                };
149
[237]150                template < typename VTX, slot SLOT >
[302]151                void add_vertex_buffer_impl( vertex_array, buffer, const std::false_type& )
[237]152                {
153                }
154
155                template < typename VTX, slot SLOT >
[302]156                void add_vertex_buffer_impl( vertex_array va, buffer vb, const std::true_type& )
[237]157                {
158                        typedef vertex_slot_info< VTX, SLOT > vinfo;
159                        typedef datatype_traits< typename vinfo::value_type > dt_traits;
[302]160                        add_vertex_buffer( va, SLOT, vb, type_to_enum< dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), false );
[237]161                }
162
163                template < typename VTX, slot SLOT >
[302]164                void add_vertex_buffer( vertex_array va, buffer vb )
[237]165                {
166                        add_vertex_buffer_impl< VTX, SLOT >( va, vb, std::integral_constant< bool, vertex_has_slot< VTX, SLOT >::value >() );
167                }
168
169                template < typename VTX >
[302]170                void add_vertex_buffers( vertex_array va, buffer vb )
[237]171                {
172                        add_vertex_buffer< VTX, slot::POSITION >  ( va, vb );
173                        add_vertex_buffer< VTX, slot::TEXCOORD >  ( va, vb );
174                        add_vertex_buffer< VTX, slot::NORMAL   >  ( va, vb );
175                        add_vertex_buffer< VTX, slot::TANGENT >   ( va, vb );
176                        add_vertex_buffer< VTX, slot::BONEINDEX > ( va, vb );
177                        add_vertex_buffer< VTX, slot::BONEWEIGHT >( va, vb );
178                        add_vertex_buffer< VTX, slot::COLOR >     ( va, vb );
[302]179                }
180
181                void add_vertex_buffers( vertex_array va, buffer buf, const mesh_raw_channel* channel )
182                {
183                        for ( uint32 s = 0; s < channel->desc.count; ++s )
184                        {
185                                const vertex_descriptor_slot& slot = channel->desc.slots[s];
186                                const datatype_info& info = get_datatype_info(slot.etype);
187                                add_vertex_buffer( va, slot.vslot, buf, info.base , info.elements, slot.offset, channel->desc.size, false );
188                        }
189                }
190
191                template < typename VTX >
192                vertex_array create_vertex_array( const VTX* v, size_t count, buffer_hint hint )
193                {
194                        // TODO: vb will not be owned or freed!
195                        vertex_array va = create_vertex_array();
196                        buffer       vb = create_buffer( VERTEX_BUFFER, hint, count * sizeof( VTX ), v );
197                        add_vertex_buffers< VTX >( va, vb );
[237]198                        return va;
199                }
200
201                template < typename VTX >
[302]202                vertex_array create_vertex_array( const std::vector< VTX >& data, buffer_hint hint )
[237]203                {
204                        return create_vertex_array( data.data(), data.size(), hint );
205                }
206
207                template < typename VTX, typename IDX >
[302]208                vertex_array create_vertex_array( const VTX* v, size_t vcount, const IDX* i, size_t icount, buffer_hint hint )
[237]209                {
[302]210                        vertex_array va = create_vertex_array( v, vcount, hint );
211                        buffer       ib = create_buffer( INDEX_BUFFER, hint, icount * sizeof( IDX ), i );
[237]212                        va->set_index_buffer( ib, type_to_enum< IDX >::type, true );
213                        return va;
214                }
215
216                template < typename VTX, typename IDX >
[302]217                vertex_array create_vertex_array( const std::vector< VTX >& data, const std::vector< IDX >& idata, buffer_hint hint )
[237]218                {
219                        return create_vertex_array( data.data(), data.size(), idata.data(), idata.size(), hint );
220                }
221
[302]222                void replace_vertex_buffer( vertex_array va, buffer vb, bool owner )
223                {
224                        vertex_array_info* info = m_vertex_arrays.get( va );
225                        if ( info )
226                        {
227                                for ( uint32 i = 0; i < info->count; ++i )
228                                {
229                                        vertex_buffer_attribute& vba = info->attr[i];
230                                        if ( vba.owner ) release( vba.vbuffer );
231                                        vba.vbuffer = vb;
232                                        vba.owner   = owner;
233                                }
234                        }
235                }
236
237                void replace_vertex_buffer( vertex_array va, buffer vb, slot location, bool owner )
238                {
239                        vertex_array_info* info = m_vertex_arrays.get( va );
240                        if ( info )
241                        {
242                                for ( uint32 i = 0; i < info->count; ++i )
243                                {
244                                        if ( info->attr[i].location == location )
245                                        {
246                                                vertex_buffer_attribute& vba = info->attr[i];
247                                                if ( vba.owner ) release( vba.vbuffer );
248                                                vba.vbuffer = vb;
249                                                vba.owner   = owner;
250                                        }
251                                }
252                        }
253                }
254
255                void update_attribute_offset( vertex_array va, slot location, size_t offset )
256                {
257                        vertex_array_info* info = m_vertex_arrays.get( va );
258                        if ( info )
259                        {
260                                for ( uint32 i = 0; i < info->count; ++i )
261                                {
262                                        if ( info->attr[i].location == location )
263                                        {
264                                                info->attr[i].offset = offset;
265                                        }
266                                }
267                        }
268                }
269
270                void set_index_buffer( vertex_array va, buffer b, datatype datatype, bool owner )
271                {
272                        vertex_array_info* info = m_vertex_arrays.get( va );
273                        if ( info )
274                        {
275                                if ( get_buffer_info( b )->type == INDEX_BUFFER )
276                                {
277                                        if (info->index.is_valid() && info->index_owner) release( info->index );
278
279                                        info->index       = b;
280                                        info->index_owner = owner;
281                                        info->index_type  = datatype;
282                                }
283                        }
284                }
285
286                void add_vertex_buffer( vertex_array va, slot location, buffer buf, datatype datatype, size_t components, size_t offset = 0, size_t stride = 0, bool owner = true )
287                {
288                        vertex_array_info* info = m_vertex_arrays.get( va );
289                        if ( info )
290                        {
291                                NV_ASSERT( info->count < vertex_array_info::MAX_ATTRIBUTES, "MAX_ATTRIBUTES reached!" );
292                                vertex_buffer_attribute& p = info->attr[ info->count ];
293                                p.vbuffer    = buf;
294                                p.dtype      = datatype;
295                                p.components = components;
296                                p.offset     = offset;
297                                p.stride     = stride;
298                                p.owner      = owner;
299                                p.location   = location;
300                                info->count++;
301                        }
302                }
303
304                buffer find_buffer( vertex_array va, slot location )
305                {
306                        vertex_array_info* info = m_vertex_arrays.get( va );
307                        if ( info )
308                        {
309                                for ( uint32 i = 0; i < info->count; ++i )
310                                {
311                                        if ( info->attr[i].location == location )
312                                        {
313                                                return info->attr[i].vbuffer;
314                                        }
315                                }
316                        }
317                        return buffer();
318                }
319
[238]320                // TODO: HINTS ARE DIFFERENT!
[302]321                vertex_array create_vertex_array( const mesh_data* data, buffer_hint hint )
[238]322                {
[302]323                        vertex_array  va = create_vertex_array();
[280]324                        const std::vector< mesh_raw_channel* >& channels = data->get_raw_channels();
325                        for ( uint32 ch = 0; ch < channels.size(); ++ch )
[238]326                        {
[280]327                                const mesh_raw_channel* channel = channels[ch];
[287]328                                if ( channel->count > 0 )
[280]329                                {
[302]330                                        buffer_type type = channel->get_buffer_type();
331                                        buffer b = create_buffer( type, hint, channel->size(), channel->data );
332                                        // TODO: no if switch
333                                        if ( type == INDEX_BUFFER )
[287]334                                        {
[302]335                                                set_index_buffer( va, b, channel->desc.slots[0].etype, true );
[287]336                                        }
337                                        else
338                                        {
[302]339                                                add_vertex_buffers( va, b, channel );
[287]340                                        }
[280]341                                }
[238]342                        }
343                        return va;
344                }
345
346
[302]347                virtual ~device()
348                {
349                        // TODO: releases buffers via gl_context which is destoryed!
350                        while ( m_vertex_arrays.size() > 0 )
351                                release( m_vertex_arrays.get_handle(0) );
352                }
353        protected:
354                entity_store< vertex_array_info, vertex_array > m_vertex_arrays;
[32]355        };
356
357} // namespace nv
358
359
360#endif // NV_DEVICE_HH
Note: See TracBrowser for help on using the repository browser.