1# ----------------------------------------------------------------------------
2# pyglet
3# Copyright (c) 2006-2008 Alex Holkner
4# Copyright (c) 2008-2020 pyglet contributors
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11#  * Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13#  * Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in
15#    the documentation and/or other materials provided with the
16#    distribution.
17#  * Neither the name of pyglet nor the names of its
18#    contributors may be used to endorse or promote products
19#    derived from this software without specific prior written
20#    permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33# POSSIBILITY OF SUCH DAMAGE.
34# ----------------------------------------------------------------------------
35
36"""Information about version and extensions of current GLU implementation.
37
38Usage::
39
40    from pyglet.gl import glu_info
41
42    if glu_info.have_extension('GLU_EXT_nurbs_tessellator'):
43        # ...
44
45If multiple contexts are in use you can use a separate GLUInfo object for each
46context.  Call `set_active_context` after switching to the desired context for
47each GLUInfo::
48
49    from pyglet.gl.glu_info import GLUInfo
50
51    info = GLUInfo()
52    info.set_active_context()
53    if info.have_version(1, 3):
54        # ...
55
56Note that GLUInfo only returns meaningful information if a context has been
57created.
58"""
59
60from ctypes import *
61import warnings
62
63from pyglet.gl.glu import *
64from pyglet.util import asstr
65
66
67class GLUInfo:
68    """Information interface for the GLU library.
69
70    A default instance is created automatically when the first OpenGL context
71    is created.  You can use the module functions as a convenience for
72    this default instance's methods.
73
74    If you are using more than one context, you must call `set_active_context`
75    when the context is active for this `GLUInfo` instance.
76    """
77    have_context = False
78    version = '0.0.0'
79    extensions = []
80
81    _have_info = False
82
83    def set_active_context(self):
84        """Store information for the currently active context.
85
86        This method is called automatically for the default context.
87        """
88        self.have_context = True
89        if not self._have_info:
90            self.extensions = asstr(cast(gluGetString(GLU_EXTENSIONS), c_char_p).value).split()
91            self.version = asstr(cast(gluGetString(GLU_VERSION), c_char_p).value)
92            self._have_info = True
93
94    def have_version(self, major, minor=0, release=0):
95        """Determine if a version of GLU is supported.
96
97        :Parameters:
98            `major` : int
99                The major revision number (typically 1).
100            `minor` : int
101                The minor revision number.
102            `release` : int
103                The release number.
104
105        :rtype: bool
106        :return: True if the requested or a later version is supported.
107        """
108        if not self.have_context:
109            warnings.warn('No GL context created yet.')
110        ver = '%s.0.0' % self.version.split(' ', 1)[0]
111        imajor, iminor, irelease = [int(v) for v in ver.split('.', 3)[:3]]
112        return imajor > major or\
113               (imajor == major and iminor > minor) or \
114               (imajor == major and iminor == minor and irelease >= release)
115
116    def get_version(self):
117        """Get the current GLU version.
118
119        :return: the GLU version
120        :rtype: str
121        """
122        if not self.have_context:
123            warnings.warn('No GL context created yet.')
124        return self.version
125
126    def have_extension(self, extension):
127        """Determine if a GLU extension is available.
128
129        :Parameters:
130            `extension` : str
131                The name of the extension to test for, including its
132                ``GLU_`` prefix.
133
134        :return: True if the extension is provided by the implementation.
135        :rtype: bool
136        """
137        if not self.have_context:
138            warnings.warn('No GL context created yet.')
139        return extension in self.extensions
140
141    def get_extensions(self):
142        """Get a list of available GLU extensions.
143
144        :return: a list of the available extensions.
145        :rtype: list of str
146        """
147        if not self.have_context:
148            warnings.warn('No GL context created yet.')
149        return self.extensions
150
151
152# Single instance useful for apps with only a single context (or all contexts
153# have same GLU driver, common case).
154_glu_info = GLUInfo()
155
156set_active_context = _glu_info.set_active_context
157have_version = _glu_info.have_version
158get_version = _glu_info.get_version
159have_extension = _glu_info.have_extension
160get_extensions = _glu_info.get_extensions
161