test_texture_pool.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. from panda3d import core
  2. import pytest
  3. import tempfile
  4. def write_image(filename, channels):
  5. img = core.PNMImage(1, 1, channels)
  6. img.set_xel_a(0, 0, (0.0, 0.25, 0.5, 0.75))
  7. assert img.write(filename)
  8. def yield_image(suffix, channels):
  9. file = tempfile.NamedTemporaryFile(suffix=suffix)
  10. path = core.Filename.from_os_specific(file.name)
  11. path.make_true_case()
  12. write_image(path, channels)
  13. yield path
  14. file.close()
  15. def register_filter(pool, tex_filter):
  16. assert pool.get_num_filters() == 0
  17. assert pool.register_filter(tex_filter)
  18. assert pool.get_num_filters() == 1
  19. def yield_registered_filter(filter_type):
  20. tex_filter = filter_type()
  21. yield tex_filter
  22. p = core.TexturePool.get_global_ptr()
  23. if p.is_filter_registered(tex_filter):
  24. p.unregister_filter(tex_filter)
  25. @pytest.fixture(scope='function')
  26. def pool():
  27. "This fixture ensures the pool is properly emptied"
  28. pool = core.TexturePool.get_global_ptr()
  29. pool.release_all_textures()
  30. yield pool
  31. pool.release_all_textures()
  32. @pytest.fixture(scope='session')
  33. def image_gray_path():
  34. "Generates a grayscale image."
  35. yield from yield_image('.bw', channels=1)
  36. @pytest.fixture(scope='session')
  37. def image_rgb_path():
  38. "Generates an RGB image."
  39. yield from yield_image('.rgb', channels=3)
  40. @pytest.fixture(scope='session')
  41. def image_rgba_path():
  42. "Generates an RGBA image."
  43. yield from yield_image('.rgba', channels=4)
  44. @pytest.fixture(scope='function')
  45. def pre_filter():
  46. "Creates a texture pool preload filter."
  47. class PreLoadTextureFilter(object):
  48. def pre_load(self, orig_filename, orig_alpha_filename,
  49. primary_file_num_channels, alpha_file_channel,
  50. read_mipmaps, options):
  51. return core.Texture('preloaded')
  52. yield from yield_registered_filter(PreLoadTextureFilter)
  53. @pytest.fixture(scope='function')
  54. def post_filter():
  55. "Creates a texture pool postload filter."
  56. class PostLoadTextureFilter(object):
  57. def post_load(self, tex):
  58. tex.set_name('postloaded')
  59. return tex
  60. yield from yield_registered_filter(PostLoadTextureFilter)
  61. @pytest.fixture(scope='function')
  62. def mix_filter():
  63. "Creates a texture pool mix filter."
  64. class MixTextureFilter(object):
  65. def pre_load(self, orig_filename, orig_alpha_filename,
  66. primary_file_num_channels, alpha_file_channel,
  67. read_mipmaps, options):
  68. return core.Texture('preloaded')
  69. def post_load(self, tex):
  70. tex.set_name(tex.get_name() + '-postloaded')
  71. return tex
  72. yield from yield_registered_filter(MixTextureFilter)
  73. @pytest.fixture(scope='function')
  74. def invalid_filter():
  75. "Creates an invalid texture filter."
  76. class InvalidTextureFilter(object):
  77. pass
  78. tex_filter = InvalidTextureFilter()
  79. yield tex_filter
  80. def test_load_texture_rgba(pool, image_rgba_path):
  81. tex = pool.load_texture(image_rgba_path)
  82. assert pool.has_texture(image_rgba_path)
  83. assert tex.num_components == 4
  84. def test_load_texture_rgba4(pool, image_rgba_path):
  85. tex = pool.load_texture(image_rgba_path, 4)
  86. assert pool.has_texture(image_rgba_path)
  87. assert tex.num_components == 4
  88. def test_load_texture_rgba3(pool, image_rgba_path):
  89. tex = pool.load_texture(image_rgba_path, 3)
  90. assert pool.has_texture(image_rgba_path)
  91. assert tex.num_components == 3
  92. def test_load_texture_rgba2(pool, image_rgba_path):
  93. tex = pool.load_texture(image_rgba_path, 2)
  94. assert pool.has_texture(image_rgba_path)
  95. assert tex.num_components == 2
  96. def test_load_texture_rgba1(pool, image_rgba_path):
  97. tex = pool.load_texture(image_rgba_path, 1)
  98. assert pool.has_texture(image_rgba_path)
  99. assert tex.num_components == 1
  100. def test_load_texture_rgb(pool, image_rgb_path):
  101. tex = pool.load_texture(image_rgb_path)
  102. assert pool.has_texture(image_rgb_path)
  103. assert tex.num_components == 3
  104. def test_load_texture_rgb4(pool, image_rgb_path):
  105. # Will not increase this
  106. tex = pool.load_texture(image_rgb_path, 4)
  107. assert pool.has_texture(image_rgb_path)
  108. assert tex.num_components == 3
  109. def test_load_texture_rgb3(pool, image_rgb_path):
  110. tex = pool.load_texture(image_rgb_path, 3)
  111. assert pool.has_texture(image_rgb_path)
  112. assert tex.num_components == 3
  113. def test_load_texture_rgb2(pool, image_rgb_path):
  114. # Cannot reduce this, since it would add an alpha channel
  115. tex = pool.load_texture(image_rgb_path, 2)
  116. assert pool.has_texture(image_rgb_path)
  117. assert tex.num_components == 3
  118. def test_load_texture_rgb1(pool, image_rgb_path):
  119. tex = pool.load_texture(image_rgb_path, 1)
  120. assert pool.has_texture(image_rgb_path)
  121. assert tex.num_components == 1
  122. def test_load_texture_rgba_alpha(pool, image_rgba_path, image_gray_path):
  123. tex = pool.load_texture(image_rgba_path, image_gray_path)
  124. assert tex.num_components == 4
  125. def test_load_texture_rgba4_alpha(pool, image_rgba_path, image_gray_path):
  126. tex = pool.load_texture(image_rgba_path, image_gray_path, 4)
  127. assert tex.num_components == 4
  128. def test_load_texture_rgba3_alpha(pool, image_rgba_path, image_gray_path):
  129. tex = pool.load_texture(image_rgba_path, image_gray_path, 3)
  130. assert tex.num_components == 4
  131. def test_load_texture_rgba2_alpha(pool, image_rgba_path, image_gray_path):
  132. #FIXME: why is this not consistent with test_load_texture_rgb2_alpha?
  133. tex = pool.load_texture(image_rgba_path, image_gray_path, 2)
  134. assert tex.num_components == 2
  135. def test_load_texture_rgba1_alpha(pool, image_rgba_path, image_gray_path):
  136. tex = pool.load_texture(image_rgba_path, image_gray_path, 1)
  137. assert tex.num_components == 2
  138. def test_load_texture_rgb_alpha(pool, image_rgb_path, image_gray_path):
  139. tex = pool.load_texture(image_rgb_path, image_gray_path)
  140. assert tex.num_components == 4
  141. def test_load_texture_rgb4_alpha(pool, image_rgb_path, image_gray_path):
  142. tex = pool.load_texture(image_rgb_path, image_gray_path, 4)
  143. assert tex.num_components == 4
  144. def test_load_texture_rgb3_alpha(pool, image_rgb_path, image_gray_path):
  145. tex = pool.load_texture(image_rgb_path, image_gray_path, 3)
  146. assert tex.num_components == 4
  147. def test_load_texture_rgb2_alpha(pool, image_rgb_path, image_gray_path):
  148. #FIXME: why is this not consistent with test_load_texture_rgba2_alpha?
  149. tex = pool.load_texture(image_rgb_path, image_gray_path, 2)
  150. assert tex.num_components == 4
  151. def test_load_texture_rgb1_alpha(pool, image_rgb_path, image_gray_path):
  152. tex = pool.load_texture(image_rgb_path, image_gray_path, 1)
  153. assert tex.num_components == 2
  154. def test_reuse_texture(pool, image_rgba_path):
  155. tex1 = pool.load_texture(image_rgba_path)
  156. tex2 = pool.load_texture(image_rgba_path)
  157. assert tex1 == tex2
  158. def test_reload_texture_fewer_channels(pool, image_rgba_path):
  159. tex = pool.load_texture(image_rgba_path)
  160. assert pool.has_texture(image_rgba_path)
  161. assert tex.num_components == 4
  162. tex = pool.load_texture(image_rgba_path, 3)
  163. assert tex.num_components == 3
  164. def test_reload_texture_more_channels(pool, image_rgba_path):
  165. tex = pool.load_texture(image_rgba_path, 3)
  166. assert pool.has_texture(image_rgba_path)
  167. assert tex.num_components == 3
  168. tex = pool.load_texture(image_rgba_path)
  169. assert tex.num_components == 4
  170. def test_reload_texture_with_alpha(pool, image_rgb_path, image_gray_path):
  171. tex = pool.load_texture(image_rgb_path)
  172. assert pool.has_texture(image_rgb_path)
  173. assert tex.num_components == 3
  174. tex = pool.load_texture(image_rgb_path, image_gray_path)
  175. assert tex.num_components == 4
  176. def test_reload_texture_without_alpha(pool, image_rgb_path, image_gray_path):
  177. tex1 = pool.load_texture(image_rgb_path, image_gray_path)
  178. assert tex1.num_components == 4
  179. tex2 = pool.load_texture(image_rgb_path)
  180. assert tex2.num_components == 3
  181. assert tex1.num_components == 4
  182. assert tex1 != tex2
  183. def test_reload_texture_different_sampler(pool, image_rgb_path):
  184. sampler = core.SamplerState()
  185. sampler.wrap_u = core.Texture.WM_clamp
  186. tex1 = pool.load_texture(image_rgb_path, 0, False, core.LoaderOptions(), sampler)
  187. assert tex1.wrap_u == core.Texture.WM_clamp
  188. sampler = core.SamplerState()
  189. sampler.wrap_u = core.Texture.WM_repeat
  190. tex2 = pool.load_texture(image_rgb_path, 0, False, core.LoaderOptions(), sampler)
  191. assert tex2.wrap_u == core.Texture.WM_repeat
  192. assert tex1.wrap_u == core.Texture.WM_clamp
  193. assert tex1 != tex2
  194. def test_reload_texture_with_force_srgb(pool, image_rgb_path):
  195. tex1 = pool.load_texture(image_rgb_path)
  196. assert tex1.format == core.Texture.F_rgb
  197. options = core.LoaderOptions()
  198. options.set_texture_flags(options.get_texture_flags() | core.LoaderOptions.TF_force_srgb)
  199. tex2 = pool.load_texture(image_rgb_path, 0, False, options)
  200. assert tex2.format == core.Texture.F_srgb
  201. assert tex1.format == core.Texture.F_rgb
  202. assert tex1 != tex2
  203. def test_reload_texture_with_format(pool, image_rgb_path):
  204. tex1 = pool.load_texture(image_rgb_path)
  205. assert tex1.format == core.Texture.F_rgb
  206. options = core.LoaderOptions()
  207. options.set_texture_format(core.Texture.F_rgb5)
  208. tex2 = pool.load_texture(image_rgb_path, 0, False, options)
  209. assert tex2.format == core.Texture.F_rgb5
  210. assert tex1.format == core.Texture.F_rgb
  211. assert tex1 != tex2
  212. def test_empty_texture_filters(pool):
  213. assert pool.get_num_filters() == 0
  214. def test_register_pre_texture_filter(pool, pre_filter):
  215. register_filter(pool, pre_filter)
  216. def test_register_post_texture_filter(pool, post_filter):
  217. register_filter(pool, post_filter)
  218. def test_register_mix_texture_filter(pool, mix_filter):
  219. register_filter(pool, mix_filter)
  220. def test_register_invalid_texture_filter(pool, invalid_filter):
  221. assert pool.get_num_filters() == 0
  222. with pytest.raises(TypeError):
  223. pool.register_filter(invalid_filter)
  224. assert pool.get_num_filters() == 0
  225. def test_register_null_texture_filter(pool):
  226. assert pool.get_num_filters() == 0
  227. with pytest.raises(TypeError):
  228. pool.register_filter(None)
  229. assert pool.get_num_filters() == 0
  230. def test_register_all_texture_filters(pool, pre_filter, post_filter, mix_filter):
  231. assert pool.get_num_filters() == 0
  232. assert pool.register_filter(pre_filter)
  233. assert pool.register_filter(post_filter)
  234. assert pool.register_filter(mix_filter)
  235. assert pool.get_num_filters() == 3
  236. def test_unregister_texture_filter(pool, mix_filter):
  237. register_filter(pool, mix_filter)
  238. assert pool.unregister_filter(mix_filter)
  239. assert pool.get_num_filters() == 0
  240. def test_clear_texture_filters(pool, pre_filter, post_filter):
  241. assert pool.get_num_filters() == 0
  242. assert pool.register_filter(pre_filter)
  243. assert pool.register_filter(post_filter)
  244. assert pool.get_num_filters() == 2
  245. pool.clear_filters()
  246. assert pool.get_num_filters() == 0
  247. def test_double_register_texture_filter(pool, mix_filter):
  248. register_filter(pool, mix_filter)
  249. assert not pool.register_filter(mix_filter)
  250. assert pool.get_num_filters() == 1
  251. def test_double_unregister_texture_filter(pool, mix_filter):
  252. register_filter(pool, mix_filter)
  253. assert pool.unregister_filter(mix_filter)
  254. assert not pool.unregister_filter(mix_filter)
  255. assert pool.get_num_filters() == 0
  256. def test_is_texture_filter_registered(pool, pre_filter, mix_filter):
  257. assert not pool.is_filter_registered(mix_filter)
  258. assert pool.register_filter(mix_filter)
  259. assert pool.is_filter_registered(mix_filter)
  260. assert not pool.is_filter_registered(pre_filter)
  261. def test_get_texture_filter(pool, pre_filter):
  262. assert not pool.get_filter(0)
  263. assert pool.register_filter(pre_filter)
  264. tex_filter = pool.get_filter(0)
  265. assert isinstance(tex_filter, core.TexturePoolFilter)
  266. assert not pool.get_filter(1)
  267. def test_texture_pre_filter(pool, pre_filter):
  268. register_filter(pool, pre_filter)
  269. texture = pool.load_texture('nonexistent')
  270. assert isinstance(texture, core.Texture)
  271. assert texture.get_name() == 'preloaded'
  272. def test_texture_post_filter(pool, post_filter, image_rgb_path):
  273. register_filter(pool, post_filter)
  274. texture = pool.load_texture(image_rgb_path, 3)
  275. assert isinstance(texture, core.Texture)
  276. assert texture.get_name() == 'postloaded'
  277. def test_texture_mix_filter(pool, mix_filter):
  278. register_filter(pool, mix_filter)
  279. texture = pool.load_texture('nonexistent')
  280. assert isinstance(texture, core.Texture)
  281. assert texture.get_name() == 'preloaded-postloaded'
  282. def test_no_texture_filter_option(pool, pre_filter, image_rgb_path):
  283. register_filter(pool, pre_filter)
  284. texture = pool.load_texture(image_rgb_path, 3, False, core.LoaderOptions(0, core.LoaderOptions.TF_no_filters))
  285. assert isinstance(texture, core.Texture)
  286. assert texture.get_name() != 'preloaded'