// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz // http://chaosforge.org/ // // This file is part of NV Libraries. // For conditions of distribution and use, see copyright notice in nv.hh /** * @file device.hh * @author Kornel Kisielewicz epyon@chaosforge.org * @brief Device class */ #ifndef NV_DEVICE_HH #define NV_DEVICE_HH #include #include #include #include #include #include #include namespace nv { class window; enum texture_slot { TEX_DIFFUSE = 0, TEX_SPECULAR = 1, TEX_NORMAL = 2, TEXTURE_0 = 0, TEXTURE_1 = 1, TEXTURE_2 = 2, TEXTURE_3 = 3, TEXTURE_4 = 4, TEXTURE_5 = 5, TEXTURE_6 = 6, TEXTURE_7 = 7, }; struct attribute { string name; int location; datatype type; int length; }; typedef std::unordered_map< string, attribute > attribute_map; struct texture_tag {}; struct buffer_tag {}; struct program_tag {}; typedef handle< uint32, 16, 16, buffer_tag > buffer; typedef handle< uint32, 16, 16, texture_tag > texture; typedef handle< uint32, 16, 16, program_tag > program; struct sampler { enum filter { LINEAR, NEAREST, NEAREST_MIPMAP_NEAREST, LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR }; enum wrap { CLAMP_TO_EDGE, CLAMP_TO_BORDER, MIRRORED_REPEAT, REPEAT }; filter filter_min; filter filter_max; wrap wrap_s; wrap wrap_t; sampler() : filter_min( LINEAR ), filter_max( LINEAR ), wrap_s( REPEAT ), wrap_t( REPEAT ) {} sampler( filter min, filter max, wrap s, wrap t ) : filter_min( min ), filter_max( max ), wrap_s( s ), wrap_t( t ) {} sampler( filter f, wrap w ) : filter_min( f ), filter_max( f ), wrap_s( w ), wrap_t( w ) {} }; struct buffer_info { buffer_type type; buffer_hint hint; size_t size; }; struct texture_info { ivec2 size; image_format format; sampler sampler; }; struct vertex_buffer_attribute { buffer vbuffer; datatype dtype; size_t components; size_t offset; size_t stride; slot location; bool owner; }; struct program_info { attribute_map m_attribute_map; uniform_map m_uniform_map; engine_uniform_list m_engine_uniforms; }; class device { friend class context; public: device() { initialize_engine_uniforms(); } virtual window* create_window( uint16 width, uint16 height, bool fullscreen ) = 0; virtual window* adopt_window( void* sys_w_handle, void* sys_dc ) = 0; virtual program create_program( const string& vs_source, const string& fs_source ) = 0; virtual buffer create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source = nullptr ) = 0; virtual image_data* create_image_data( const std::string& filename ) = 0; // temporary virtual texture create_texture( ivec2 size, image_format aformat, sampler asampler, void* data = nullptr ) = 0; virtual void release( texture ) = 0; virtual void release( buffer ) = 0; virtual void release( program ) = 0; virtual const texture_info* get_texture_info( texture ) const = 0; virtual const buffer_info* get_buffer_info( buffer ) const = 0; virtual uint32 get_ticks() = 0; virtual void delay( uint32 ms ) = 0; virtual const string& get_shader_header() const = 0; virtual texture create_texture( image_data* data, sampler asampler ) { return create_texture( data->get_size(), data->get_format(), asampler, (void*)data->get_data() ); } int try_get_attribute_location( program p, const string& name ) const { return get_attribute_location( p, name, false ); } virtual int get_attribute_location( program p, const string& name, bool fatal = true ) const = 0; template < typename T > void set_uniform_array( program p, const string& name, const T* value, uint32 count, bool fatal = true ) { uniform_base* base = get_uniform( p, name, fatal ); if ( base != nullptr ) { if ( base->type_check( type_to_enum::type ) ) { // TODO: nicer check NV_ASSERT( (int)count <= base->get_length(), "LENGTH CHECK FAIL" ); ((uniform*)( base ))->set_value( value, count ); } } } template < typename T > void set_uniform_array( const string& name, const std::vector& value ) { set_uniform_array( program p, name, (const T*)value.data(), value.size() ); } template < typename T > void set_opt_uniform_array( program p, const string& name, const T* value, uint32 count ) { set_uniform_array( p, name, value, count, false ); } template < typename T > void set_opt_uniform_array( program p, const string& name, const std::vector& value ) { set_uniform_array( p, name, (const T*)value.data(), value.size(), false ); } template < typename T > void set_uniform( program p, const string& name, const T& value, bool fatal = true ) { uniform_base* base = get_uniform( p, name, fatal ); if ( base != nullptr ) { if ( base->type_check( type_to_enum::type ) ) { ((uniform*)( base ))->set_value( value ); } } } template < typename T > void set_opt_uniform( program p, const string& name, const T& value ) { set_uniform( p, name, value, false ); } virtual ~device() { destroy_engine_uniforms(); } // This is done this way to avoid compilation unit creation static engine_uniform_factory_map& get_uniform_factory() { static engine_uniform_factory_map s_engine_uniform_factory_map; return s_engine_uniform_factory_map; } // This is done this way to avoid compilation unit creation static engine_link_uniform_factory_map& get_link_uniform_factory() { static engine_link_uniform_factory_map s_engine_link_uniform_factory_map; return s_engine_link_uniform_factory_map; } virtual void prepare_program( program p ) = 0; protected: virtual uniform_base* get_uniform( program p, const string& name, bool fatal = true ) const = 0; void initialize_engine_uniforms() { engine_uniform_factory_map& factory_map = get_uniform_factory(); factory_map[ "nv_m_view" ] = new engine_uniform_factory< engine_uniform_m_view >(); factory_map[ "nv_m_view_inv" ] = new engine_uniform_factory< engine_uniform_m_view_inv >(); factory_map[ "nv_m_model" ] = new engine_uniform_factory< engine_uniform_m_model >(); factory_map[ "nv_m_model_inv" ] = new engine_uniform_factory< engine_uniform_m_model_inv >(); factory_map[ "nv_m_modelview" ] = new engine_uniform_factory< engine_uniform_m_modelview >(); factory_map[ "nv_m_projection" ] = new engine_uniform_factory< engine_uniform_m_projection >(); factory_map[ "nv_m_normal" ] = new engine_uniform_factory< engine_uniform_m_normal >(); factory_map[ "nv_m_mvp" ] = new engine_uniform_factory< engine_uniform_m_mvp >(); factory_map[ "nv_v_camera_position" ] = new engine_uniform_factory< engine_uniform_v_camera_position >(); factory_map[ "nv_v_camera_direction" ] = new engine_uniform_factory< engine_uniform_v_camera_direction >(); engine_link_uniform_factory_map& factory_link_map = get_link_uniform_factory(); factory_link_map[ "nv_texture_0" ] = new engine_link_uniform_int<0>(); factory_link_map[ "nv_texture_1" ] = new engine_link_uniform_int<1>(); factory_link_map[ "nv_texture_2" ] = new engine_link_uniform_int<2>(); factory_link_map[ "nv_texture_3" ] = new engine_link_uniform_int<3>(); factory_link_map[ "nv_texture_4" ] = new engine_link_uniform_int<4>(); factory_link_map[ "nv_texture_5" ] = new engine_link_uniform_int<5>(); factory_link_map[ "nv_texture_6" ] = new engine_link_uniform_int<6>(); factory_link_map[ "nv_texture_7" ] = new engine_link_uniform_int<7>(); factory_link_map[ "nv_t_diffuse" ] = new engine_link_uniform_int<0>(); factory_link_map[ "nv_t_specular"] = new engine_link_uniform_int<1>(); factory_link_map[ "nv_t_normal" ] = new engine_link_uniform_int<2>(); } void destroy_engine_uniforms() { for ( auto& i : get_uniform_factory() ) delete i.second; for ( auto& i : get_link_uniform_factory() ) delete i.second; get_uniform_factory().clear(); get_link_uniform_factory().clear(); } }; } // namespace nv #endif // NV_DEVICE_HH