diff --git a/panda/src/egg/eggBinMaker.cxx b/panda/src/egg/eggBinMaker.cxx index 24e745a53c..f969a294fc 100644 --- a/panda/src/egg/eggBinMaker.cxx +++ b/panda/src/egg/eggBinMaker.cxx @@ -212,9 +212,10 @@ collect_nodes(EggGroupNode *group) { // And remove it from the scene graph. group->erase(i); + } - } else if (node->is_of_type(EggGroupNode::get_class_type())) { - // Here's a normal group node, not to be binned. Traverse. + if (node->is_of_type(EggGroupNode::get_class_type())) { + // Recursively traverse. collect_nodes(DCAST(EggGroupNode, node)); } diff --git a/panda/src/egg/eggGroup.cxx b/panda/src/egg/eggGroup.cxx index 8355504872..b1bff26c8a 100644 --- a/panda/src/egg/eggGroup.cxx +++ b/panda/src/egg/eggGroup.cxx @@ -365,7 +365,7 @@ write_object_types(ostream &out, int indent_level) const { //////////////////////////////////////////////////////////////////// // Function: EggGroup::write_decal_flags // Access: Public -// Description: Writes the flags related to decalling, if any. +// Description: Writes the flags related to decaling, if any. //////////////////////////////////////////////////////////////////// void EggGroup:: write_decal_flags(ostream &out, int indent_level) const { @@ -544,6 +544,25 @@ determine_indexed() { return EggGroupNode::determine_indexed(); } +//////////////////////////////////////////////////////////////////// +// Function: EggGroup::determine_decal +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// at this level or above that has the "decal" flag +// set. Returns the value of the decal flag if it +// is found, or false if it is not. +// +// In other words, returns true if the "decal" flag is +// in effect for the indicated node, false otherwise. +//////////////////////////////////////////////////////////////////// +bool EggGroup:: +determine_decal() { + if (get_decal_flag()) { + return true; + } + return EggGroupNode::determine_decal(); +} + //////////////////////////////////////////////////////////////////// // Function: EggGroup::ref_vertex // Access: Public diff --git a/panda/src/egg/eggGroup.h b/panda/src/egg/eggGroup.h index 29c330598f..82ce25d34b 100644 --- a/panda/src/egg/eggGroup.h +++ b/panda/src/egg/eggGroup.h @@ -120,6 +120,7 @@ PUBLISHED: virtual EggRenderMode *determine_draw_order(); virtual EggRenderMode *determine_bin(); virtual bool determine_indexed(); + virtual bool determine_decal(); void set_group_type(GroupType type); INLINE GroupType get_group_type() const; diff --git a/panda/src/egg/eggNode.cxx b/panda/src/egg/eggNode.cxx index fb4b5e7fa1..e6b5d46840 100644 --- a/panda/src/egg/eggNode.cxx +++ b/panda/src/egg/eggNode.cxx @@ -198,6 +198,26 @@ determine_indexed() { return _parent->determine_indexed(); } +//////////////////////////////////////////////////////////////////// +// Function: EggNode::determine_decal +// Access: Public, Virtual +// Description: Walks back up the hierarchy, looking for an EggGroup +// at this level or above that has the "decal" flag +// set. Returns the value of the decal flag if it +// is found, or false if it is not. +// +// In other words, returns true if the "decal" flag is +// in effect for the indicated node, false otherwise. +//////////////////////////////////////////////////////////////////// +bool EggNode:: +determine_decal() { + if (_parent == (EggGroupNode *)NULL) { + // Too bad; we're done. + return false; + } + return _parent->determine_decal(); +} + //////////////////////////////////////////////////////////////////// // Function: EggNode::parse_egg diff --git a/panda/src/egg/eggNode.h b/panda/src/egg/eggNode.h index dfc170e071..20867c0799 100644 --- a/panda/src/egg/eggNode.h +++ b/panda/src/egg/eggNode.h @@ -80,6 +80,7 @@ PUBLISHED: virtual EggRenderMode *determine_draw_order(); virtual EggRenderMode *determine_bin(); virtual bool determine_indexed(); + virtual bool determine_decal(); virtual void write(ostream &out, int indent_level) const=0; bool parse_egg(const string &egg_syntax); diff --git a/panda/src/egg2pg/characterMaker.cxx b/panda/src/egg2pg/characterMaker.cxx index a173989cd8..a30b20b6b2 100644 --- a/panda/src/egg2pg/characterMaker.cxx +++ b/panda/src/egg2pg/characterMaker.cxx @@ -238,7 +238,6 @@ egg_to_slider(const string &name) { CharacterJointBundle *CharacterMaker:: make_bundle() { build_joint_hierarchy(_egg_root, _skeleton_root); - _bundle->sort_descendants(); if (use_qpgeom) { // The new, experimental Geom system. @@ -251,8 +250,9 @@ make_bundle() { _character_node->_computed_vertices = _comp_verts_maker.make_computed_vertices(_character_node, *this); } + _bundle->sort_descendants(); parent_joint_nodes(_skeleton_root); - + return _bundle; } diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index df12a69fac..3729f33265 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1493,7 +1493,7 @@ separate_switches(EggNode *egg_node) { bool parent_has_switch = false; if (egg_node->is_of_type(EggGroup::get_class_type())) { EggGroup *egg_group = DCAST(EggGroup, egg_node); - parent_has_switch = egg_group->get_switch_flag(); + parent_has_switch = egg_group->get_switch_flag() || egg_group->has_lod(); } if (egg_node->is_of_type(EggGroupNode::get_class_type())) { @@ -1778,7 +1778,11 @@ make_node(EggGroup *egg_group, PandaNode *parent) { bool all_polysets = false; bool any_hidden = false; if (use_qpgeom) { - check_for_polysets(egg_group, all_polysets, any_hidden); + // We don't want to ever create a GeomNode under a "decal" flag, + // since that can confuse the decal reparenting. + if (!egg_group->determine_decal()) { + check_for_polysets(egg_group, all_polysets, any_hidden); + } } if (all_polysets && !any_hidden) { diff --git a/panda/src/gobj/qpgeom.cxx b/panda/src/gobj/qpgeom.cxx index be341bd113..8103045cab 100644 --- a/panda/src/gobj/qpgeom.cxx +++ b/panda/src/gobj/qpgeom.cxx @@ -513,7 +513,10 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomMunger *munger, for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) { - (*pi)->draw(gsg); + const qpGeomPrimitive *primitive = (*pi); + if (primitive->get_num_vertices() != 0) { + (*pi)->draw(gsg); + } } gsg->end_draw_primitives(); } diff --git a/panda/src/gobj/qpgeomVertexArrayFormat.I b/panda/src/gobj/qpgeomVertexArrayFormat.I index 1e5df15853..41148ce9ec 100644 --- a/panda/src/gobj/qpgeomVertexArrayFormat.I +++ b/panda/src/gobj/qpgeomVertexArrayFormat.I @@ -30,6 +30,25 @@ is_registered() const { return _is_registered; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::register_format +// Access: Published, Static +// Description: Adds the indicated format to the registry, if there +// is not an equivalent format already there; in either +// case, returns the pointer to the equivalent format +// now in the registry. +// +// This is similar to +// GeomVertexFormat::register_format(), except that you +// generally need not call it explicitly. Calling +// GeomVertexFormat::register_format() automatically +// registers all of the nested array formats. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexArrayFormat) qpGeomVertexArrayFormat:: +register_format(const qpGeomVertexArrayFormat *format) { + return get_registry()->register_format((qpGeomVertexArrayFormat *)format); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexArrayFormat::get_stride // Access: Published @@ -113,6 +132,19 @@ has_column(const InternalName *name) const { return (get_column(name) != (qpGeomVertexColumn *)NULL); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::get_registry +// Access: Private +// Description: Returns the global registry object. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexArrayFormat::Registry *qpGeomVertexArrayFormat:: +get_registry() { + if (_registry == (Registry *)NULL) { + make_registry(); + } + return _registry; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexArrayFormat::consider_sort_columns // Access: Private diff --git a/panda/src/gobj/qpgeomVertexArrayFormat.cxx b/panda/src/gobj/qpgeomVertexArrayFormat.cxx index a74050d343..2af7de7b1e 100644 --- a/panda/src/gobj/qpgeomVertexArrayFormat.cxx +++ b/panda/src/gobj/qpgeomVertexArrayFormat.cxx @@ -25,6 +25,7 @@ #include "bamWriter.h" #include "indirectLess.h" +qpGeomVertexArrayFormat::Registry *qpGeomVertexArrayFormat::_registry = NULL; TypeHandle qpGeomVertexArrayFormat::_type_handle; //////////////////////////////////////////////////////////////////// @@ -185,6 +186,9 @@ operator = (const qpGeomVertexArrayFormat ©) { //////////////////////////////////////////////////////////////////// qpGeomVertexArrayFormat:: ~qpGeomVertexArrayFormat() { + if (is_registered()) { + get_registry()->unregister_format(this); + } Columns::iterator ci; for (ci = _columns.begin(); ci != _columns.end(); ++ci) { delete (*ci); @@ -501,6 +505,18 @@ sort_columns() { sort(_columns.begin(), _columns.end(), IndirectLess()); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::make_registry +// Access: Private +// Description: Returns the global registry object. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +make_registry() { + if (_registry == (Registry *)NULL) { + _registry = new Registry; + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexArrayFormat::do_register // Access: Private @@ -511,6 +527,17 @@ do_register() { nassertv(!_is_registered); _is_registered = true; } + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::do_unregister +// Access: Private +// Description: Called internally when the format is unregistered. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat:: +do_unregister() { + nassertv(_is_registered); + _is_registered = false; +} //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexArrayFormat::register_with_read_factory @@ -613,3 +640,64 @@ fillin(DatagramIterator &scan, BamReader *manager) { } _columns_unsorted = false; } + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Registry::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +qpGeomVertexArrayFormat::Registry:: +Registry() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Registry::register_format +// Access: Public +// Description: Adds the indicated format to the registry, if there +// is not an equivalent format already there; in either +// case, returns the pointer to the equivalent format +// now in the registry. +// +// This must be called before a format may be used in a +// Geom. After this call, you should discard the +// original pointer you passed in (which may or may not +// now be invalid) and let its reference count decrement +// normally; you should use only the returned value from +// this point on. +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexArrayFormat) qpGeomVertexArrayFormat::Registry:: +register_format(qpGeomVertexArrayFormat *format) { + if (format->is_registered()) { + return format; + } + + // Save the incoming pointer in a local PointerTo, so that if it has + // a zero reference count and is not added into the map below, it + // will be automatically deleted when this function returns. + PT(qpGeomVertexArrayFormat) pt_format = format; + + ArrayFormats::iterator fi = _formats.insert(format).first; + + qpGeomVertexArrayFormat *new_format = (*fi); + if (!new_format->is_registered()) { + new_format->do_register(); + } + + return new_format; +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexArrayFormat::Registry::unregister_format +// Access: Public +// Description: Removes the indicated format from the registry. +// Normally this should not be done until the format is +// destructing. +//////////////////////////////////////////////////////////////////// +void qpGeomVertexArrayFormat::Registry:: +unregister_format(qpGeomVertexArrayFormat *format) { + nassertv(format->is_registered()); + ArrayFormats::iterator fi = _formats.find(format); + nassertv(fi != _formats.end()); + _formats.erase(fi); + format->do_unregister(); +} diff --git a/panda/src/gobj/qpgeomVertexArrayFormat.h b/panda/src/gobj/qpgeomVertexArrayFormat.h index a851bae083..7bcb0bca9c 100644 --- a/panda/src/gobj/qpgeomVertexArrayFormat.h +++ b/panda/src/gobj/qpgeomVertexArrayFormat.h @@ -22,6 +22,7 @@ #include "pandabase.h" #include "typedWritableReferenceCount.h" #include "qpgeomVertexColumn.h" +#include "indirectCompareTo.h" #include "pvector.h" #include "pmap.h" @@ -90,6 +91,7 @@ PUBLISHED: ~qpGeomVertexArrayFormat(); INLINE bool is_registered() const; + INLINE static CPT(qpGeomVertexArrayFormat) register_format(const qpGeomVertexArrayFormat *format); INLINE int get_stride() const; INLINE void set_stride(int stride); @@ -123,9 +125,15 @@ public: int compare_to(const qpGeomVertexArrayFormat &other) const; private: + class Registry; + INLINE static Registry *get_registry(); + static void make_registry(); + + void do_register(); + void do_unregister(); + INLINE void consider_sort_columns() const; void sort_columns(); - void do_register(); bool _is_registered; int _stride; @@ -139,6 +147,19 @@ private: typedef pmap ColumnsByName; ColumnsByName _columns_by_name; + // This is the global registry of all currently-in-use array formats. + typedef pset > ArrayFormats; + class EXPCL_PANDA Registry { + public: + Registry(); + CPT(qpGeomVertexArrayFormat) register_format(qpGeomVertexArrayFormat *format); + void unregister_format(qpGeomVertexArrayFormat *format); + + ArrayFormats _formats; + }; + + static Registry *_registry; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 2320f173dd..b55042827a 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -1394,10 +1394,9 @@ finalize(BamReader *manager) { for (size_t i = 0; i < cdata->_arrays.size(); ++i) { CPT(qpGeomVertexArrayFormat) new_array_format = new_format->get_array(i); - CPT(qpGeomVertexArrayFormat) old_array_format = _format->get_array(i); - nassertv(cdata->_arrays[i]->_array_format == old_array_format); + nassertv(cdata->_arrays[i]->_array_format->compare_to(*new_array_format) == 0); - manager->change_pointer(old_array_format, new_array_format); + manager->change_pointer(cdata->_arrays[i]->_array_format, new_array_format); cdata->_arrays[i]->_array_format = new_array_format; } diff --git a/panda/src/gobj/qpgeomVertexFormat.cxx b/panda/src/gobj/qpgeomVertexFormat.cxx index ea0394b846..a5286c9c74 100644 --- a/panda/src/gobj/qpgeomVertexFormat.cxx +++ b/panda/src/gobj/qpgeomVertexFormat.cxx @@ -503,9 +503,10 @@ do_register() { nassertv(_columns_by_name.empty()); for (int array = 0; array < (int)_arrays.size(); ++array) { - const qpGeomVertexArrayFormat *array_format = _arrays[array]; + CPT(qpGeomVertexArrayFormat) array_format = _arrays[array]; if (!array_format->is_registered()) { - ((qpGeomVertexArrayFormat *)array_format)->do_register(); + array_format = qpGeomVertexArrayFormat::register_format(array_format); + _arrays[array] = (qpGeomVertexArrayFormat *)array_format.p(); } // Now add the names to the index. @@ -580,7 +581,6 @@ do_register() { } } - _is_registered = true; get_array_info(InternalName::get_vertex(), _vertex_array_index, diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index ecbba81f77..756ae30983 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1460,11 +1460,20 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) { //////////////////////////////////////////////////////////////////// void Texture:: write_datagram(BamWriter *manager, Datagram &me) { - bool has_rawdata = (bam_texture_mode == BTM_rawdata); - Filename filename = get_filename(); Filename alpha_filename = get_alpha_filename(); + // Write out the texture's raw pixel data if (a) the current Bam + // Texture Mode requires that, or (b) there's no filename, so the + // file can't be loaded up from disk, but the raw pixel data is + // currently available in RAM. + + // Otherwise, we just write out the filename, and assume whoever + // loads the bam file later will have access to the image file on + // disk. + bool has_rawdata = + (bam_texture_mode == BTM_rawdata || (has_ram_image() && filename.empty())); + switch (bam_texture_mode) { case BTM_unchanged: case BTM_rawdata: diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx index 0e3f4a7e9f..df12f13be5 100644 --- a/panda/src/pgraph/cullResult.cxx +++ b/panda/src/pgraph/cullResult.cxx @@ -128,8 +128,9 @@ add_object(CullableObject *object, const CullTraverser *traverser) { get_dual_transparent_state_decals() : get_dual_transparent_state(); transparent_part->_state = state->compose(transparent_state); - transparent_part->munge_geom(get_geom_munger(transparent_part->_state), - traverser); + transparent_part->munge_geom + (_gsg, get_geom_munger(transparent_part->_state), + traverser); CullBin *bin = get_bin(transparent_part->_state->get_bin_index()); nassertv(bin != (CullBin *)NULL); bin->add_object(transparent_part); @@ -156,7 +157,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) { // Munge vertices as needed for the GSG's requirements, and the // object's current state. - object->munge_geom(get_geom_munger(object->_state), traverser); + object->munge_geom(_gsg, get_geom_munger(object->_state), traverser); CullBin *bin = get_bin(object->_state->get_bin_index()); nassertv(bin != (CullBin *)NULL); diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 1008b19a2a..323d8591f4 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -41,7 +41,8 @@ TypeHandle CullableObject::_type_handle; // and/or its vertices. //////////////////////////////////////////////////////////////////// void CullableObject:: -munge_geom(const qpGeomMunger *munger, const CullTraverser *traverser) { +munge_geom(GraphicsStateGuardianBase *gsg, + const qpGeomMunger *munger, const CullTraverser *traverser) { if (_geom != (Geom *)NULL) { // Temporary test and dcast until the experimental Geom rewrite // becomes the actual Geom rewrite. @@ -93,7 +94,11 @@ munge_geom(const qpGeomMunger *munger, const CullTraverser *traverser) { } } if (_next != (CullableObject *)NULL) { - _next->munge_geom(munger, traverser); + if (_next->_state != (RenderState *)NULL) { + _next->munge_geom(gsg, gsg->get_geom_munger(_next->_state), traverser); + } else { + _next->munge_geom(gsg, munger, traverser); + } } } diff --git a/panda/src/pgraph/cullableObject.h b/panda/src/pgraph/cullableObject.h index a5c42f1ae0..e318f64d9d 100644 --- a/panda/src/pgraph/cullableObject.h +++ b/panda/src/pgraph/cullableObject.h @@ -57,7 +57,8 @@ public: INLINE bool has_decals() const; - void munge_geom(const qpGeomMunger *munger, const CullTraverser *traverser); + void munge_geom(GraphicsStateGuardianBase *gsg, + const qpGeomMunger *munger, const CullTraverser *traverser); INLINE void draw(GraphicsStateGuardianBase *gsg); public: diff --git a/panda/src/pgraph/drawCullHandler.cxx b/panda/src/pgraph/drawCullHandler.cxx index 6b2de87b67..49e872e21b 100644 --- a/panda/src/pgraph/drawCullHandler.cxx +++ b/panda/src/pgraph/drawCullHandler.cxx @@ -35,7 +35,7 @@ void DrawCullHandler:: record_object(CullableObject *object, const CullTraverser *traverser) { // Munge vertices as needed for the GSG's requirements, and the // object's current state. - object->munge_geom(_gsg->get_geom_munger(object->_state), traverser); + object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state), traverser); // And draw the object, then dispense with it. draw(object, _gsg); diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index 18a901037b..b8fd345b12 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -127,23 +127,38 @@ void wglGraphicsStateGuardian:: reset() { GLGraphicsStateGuardian::reset(); - _supports_pbuffer = has_extension("WGL_ARB_pbuffer"); - _supports_pixel_format = has_extension("WGL_ARB_pixel_format"); - _supports_wgl_multisample = has_extension("WGL_ARB_multisample"); - _supports_render_texture = has_extension("WGL_ARB_render_texture"); + _supports_swap_control = has_extension("WGL_EXT_swap_control"); - _wglCreatePbufferARB = - (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"); - _wglGetPbufferDCARB = - (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB"); - _wglReleasePbufferDCARB = - (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB"); - _wglDestroyPbufferARB = - (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB"); - _wglQueryPbufferARB = - (PFNWGLQUERYPBUFFERARBPROC)wglGetProcAddress("wglQueryPbufferARB"); + if (_supports_swap_control) { + _wglSwapIntervalEXT = + (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); + if (_wglSwapIntervalEXT == NULL) { + wgldisplay_cat.error() + << "Driver claims to support WGL_EXT_swap_control extension, but does not define all functions.\n"; + _supports_swap_control = false; + } + } + + if (_supports_swap_control) { + // Set the video-sync setting up front, if we have the extension + // that supports it. + _wglSwapIntervalEXT(sync_video ? 1 : 0); + } + + _supports_pbuffer = has_extension("WGL_ARB_pbuffer"); if (_supports_pbuffer) { + _wglCreatePbufferARB = + (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB"); + _wglGetPbufferDCARB = + (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB"); + _wglReleasePbufferDCARB = + (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB"); + _wglDestroyPbufferARB = + (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB"); + _wglQueryPbufferARB = + (PFNWGLQUERYPBUFFERARBPROC)wglGetProcAddress("wglQueryPbufferARB"); + if (_wglCreatePbufferARB == NULL || _wglGetPbufferDCARB == NULL || _wglReleasePbufferDCARB == NULL || @@ -155,14 +170,16 @@ reset() { } } - _wglGetPixelFormatAttribivARB = - (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribivARB"); - _wglGetPixelFormatAttribfvARB = - (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribfvARB"); - _wglChoosePixelFormatARB = - (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + _supports_pixel_format = has_extension("WGL_ARB_pixel_format"); if (_supports_pixel_format) { + _wglGetPixelFormatAttribivARB = + (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribivARB"); + _wglGetPixelFormatAttribfvARB = + (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress("wglGetPixelFormatAttribfvARB"); + _wglChoosePixelFormatARB = + (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + if (_wglGetPixelFormatAttribivARB == NULL || _wglGetPixelFormatAttribfvARB == NULL || _wglChoosePixelFormatARB == NULL) { @@ -172,14 +189,17 @@ reset() { } } - _wglBindTexImageARB = - (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress("wglBindTexImageARB"); - _wglReleaseTexImageARB = - (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress("wglReleaseTexImageARB"); - _wglSetPbufferAttribARB = - (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress("wglSetPbufferAttribARB"); + _supports_wgl_multisample = has_extension("WGL_ARB_multisample"); + + _supports_render_texture = has_extension("WGL_ARB_render_texture"); if (_supports_render_texture) { + _wglBindTexImageARB = + (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress("wglBindTexImageARB"); + _wglReleaseTexImageARB = + (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress("wglReleaseTexImageARB"); + _wglSetPbufferAttribARB = + (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress("wglSetPbufferAttribARB"); if (_wglBindTexImageARB == NULL || _wglReleaseTexImageARB == NULL || _wglSetPbufferAttribARB == NULL) { diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.h b/panda/src/wgldisplay/wglGraphicsStateGuardian.h index 5f6d29b863..9c764e91b2 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.h +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.h @@ -84,6 +84,9 @@ private: static bool _twindow_class_registered; public: + bool _supports_swap_control; + PFNWGLSWAPINTERVALEXTPROC _wglSwapIntervalEXT; + bool _supports_pbuffer; PFNWGLCREATEPBUFFERARBPROC _wglCreatePbufferARB; PFNWGLGETPBUFFERDCARBPROC _wglGetPbufferDCARB;