Package glitter :: Package contexts :: Module textures
[hide private]
[frames] | no frames]

Source Code for Module glitter.contexts.textures

  1  """Descriptors for texture image units. 
  2   
  3  @author: Stephan Wenger 
  4  @date: 2012-02-29 
  5  """ 
  6   
  7  import itertools as _itertools 
  8   
  9  import glitter.raw as _gl 
 10  from glitter.utils import BindableObject, GlitterError 
 11  from glitter.contexts.proxies import BindingProxy 
 12   
13 -class TextureUnit(BindableObject):
14 """Proxy for a texture unit. 15 16 @warning: For internal use by L{TextureUnitList} only. Do not instantiate 17 or use directly; use the methods of L{TextureUnitList} instead. 18 """ 19 20 _binding = "active_texture" 21
22 - def __init__(self, context, _id):
23 super(TextureUnit, self).__init__(context=context) 24 self._context = context 25 self._id = _id 26 self._use_count = 0
27
28 - def __str__(self):
29 return "GL_TEXTURE%d" % (self._id - _gl.GL_TEXTURE0)
30
31 - def activate(self):
32 self._context.active_texture = self
33
34 - def is_available(self):
35 return self._use_count == 0
36 37 texture_binding_1d = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_1D ]) 38 texture_binding_1d_array = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_1D_ARRAY ]) 39 texture_binding_2d = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_2D ]) 40 texture_binding_2d_array = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_2D_ARRAY ]) 41 texture_binding_2d_multisample = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_2D_MULTISAMPLE ]) 42 texture_binding_2d_multisample_array = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_2D_MULTISAMPLE_ARRAY]) 43 texture_binding_3d = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_3D ]) 44 texture_binding_buffer = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_BUFFER ]) 45 texture_binding_cube_map = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_CUBE_MAP ]) 46 texture_binding_rectangle = BindingProxy(_gl.glBindTexture, [_gl.GL_TEXTURE_RECTANGLE ]) 47 sampler_binding = BindingProxy(_gl.glBindSampler, ["_unit" ])
48
49 -class TextureUnitList(object):
50 """Proxy for the list of available texture units. 51 52 @warning: C{TextureUnitList}s are created by their respective context only. 53 Do not instantiate them directly. Using the C{TextureUnitList}'s L{bind} 54 and L{release} methods directly is usually not necessary; L{Shader}s bind 55 their textures automatically, and the L{bind<Texture.bind>} method of 56 L{Texture}s is delegated to the C{TextureUnitList}. 57 """ 58
59 - def __init__(self, context):
60 self._context = context 61 num_units = context.max_combined_texture_image_units 62 if not 0 < num_units < 4096: # sanity check 63 raise GlitterError("implausible number of texture units detected; are you sure there is a current OpenGL context?") 64 self._texture_units = [TextureUnit(context, _gl.GL_TEXTURE0 + i) for i in range(num_units)] 65 self._context.active_texture = self[0] 66 self._bound_textures = dict()
67
68 - def __getitem__(self, index):
69 return self._texture_units[index]
70
71 - def __len__(self):
72 return len(self._texture_units)
73
74 - def __str__(self):
75 return "[%d texture units]" % len(self)
76
77 - def __repr__(self):
78 return str(self)
79
80 - def bind(self, texture):
81 """Bind `texture` to a free unit and return the unit id.""" 82 if texture in self._bound_textures: 83 unit = self._bound_textures[texture] 84 unit._use_count += 1 85 else: 86 try: 87 unit = _itertools.dropwhile(lambda x: not x.is_available(), self).next() 88 except StopIteration: 89 raise RuntimeError("no free texture units available") 90 setattr(unit, texture._binding, texture) 91 self._bound_textures[texture] = unit 92 unit._use_count = 1 93 return unit._id - _gl.GL_TEXTURE0
94
95 - def release(self, texture):
96 """Unbind `texture`.""" 97 unit = self._bound_textures[texture] 98 if unit._use_count == 1: 99 setattr(unit, texture._binding, None) 100 del self._bound_textures[texture] 101 unit._use_count = 0 102 else: 103 unit._use_count -= 1
104