a382424667c7877489362b64285cd0ed1475675c
[platform/upstream/mesa.git] / src / gallium / state_trackers / python / tests / texture_sample.py
1 #!/usr/bin/env python
2 ##########################################################################
3
4 # Copyright 2009 VMware, Inc.
5 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 # All Rights Reserved.
7
8 # Permission is hereby granted, free of charge, to any person obtaining a
9 # copy of this software and associated documentation files (the
10 # "Software"), to deal in the Software without restriction, including
11 # without limitation the rights to use, copy, modify, merge, publish,
12 # distribute, sub license, and/or sell copies of the Software, and to
13 # permit persons to whom the Software is furnished to do so, subject to
14 # the following conditions:
15
16 # The above copyright notice and this permission notice (including the
17 # next paragraph) shall be included in all copies or substantial portions
18 # of the Software.
19
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 # IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
24 # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 ##########################################################################
29
30
31 from gallium import *
32 from base import *
33
34
35 def lods(*dims):
36     size = max(dims)
37     lods = 0
38     while size:
39         lods += 1
40         size >>= 1
41     return lods
42
43
44 def minify(dims, level = 1):
45     return [max(dim>>level, 1) for dim in dims]
46
47
48 def tex_coords(texture, face, level, zslice):
49     st = [ 
50         [0.0, 0.0], 
51         [1.0, 0.0], 
52         [1.0, 1.0], 
53         [0.0, 1.0],
54     ] 
55     
56     if texture.target == PIPE_TEXTURE_2D:
57         return [[s, t, 0.0] for s, t in st]
58     elif texture.target == PIPE_TEXTURE_3D:
59         depth = texture.get_depth(level)
60         if depth > 1:
61             r = float(zslice)/float(depth - 1)
62         else:
63             r = 0.0
64         return [[s, t, r] for s, t in st]
65     elif texture.target == PIPE_TEXTURE_CUBE:
66         result = []
67         for s, t in st:
68             # See http://developer.nvidia.com/object/cube_map_ogl_tutorial.html
69             sc = 2.0*s - 1.0
70             tc = 2.0*t - 1.0
71             if face == PIPE_TEX_FACE_POS_X:
72                 rx = 1.0
73                 ry = -tc
74                 rz = -sc
75             if face == PIPE_TEX_FACE_NEG_X:
76                 rx = -1.0
77                 ry = -tc
78                 rz = sc
79             if face == PIPE_TEX_FACE_POS_Y:
80                 rx = sc
81                 ry = 1.0
82                 rz = tc
83             if face == PIPE_TEX_FACE_NEG_Y:
84                 rx = sc
85                 ry = -1.0
86                 rz = -tc
87             if face == PIPE_TEX_FACE_POS_Z:
88                 rx = sc
89                 ry = -tc
90                 rz = 1.0
91             if face == PIPE_TEX_FACE_NEG_Z:
92                 rx = -sc
93                 ry = -tc
94                 rz = -1.0
95             result.append([rx, ry, rz])
96         return result
97
98 def is_pot(n):
99     return n & (n - 1) == 0
100       
101                 
102 class TextureTest(TestCase):
103     
104     tags = (
105         'target',
106         'format',
107         'width',
108         'height',
109         'depth',
110         'last_level',
111         'face',
112         'level',
113         'zslice',
114     )
115
116     def test(self):
117         dev = self.dev
118         
119         target = self.target
120         format = self.format
121         width = self.width
122         height = self.height
123         depth = self.depth
124         last_level = self.last_level
125         face = self.face
126         level = self.level
127         zslice = self.zslice
128         
129         tex_usage = PIPE_TEXTURE_USAGE_SAMPLER
130         geom_flags = 0
131         if width != height:
132             geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
133         if not is_pot(width) or not is_pot(height) or not is_pot(depth):
134             geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
135         
136         if not dev.is_format_supported(format, target, tex_usage, geom_flags):
137             raise TestSkip
138         
139         ctx = self.dev.context_create()
140     
141         # disabled blending/masking
142         blend = Blend()
143         blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
144         blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
145         blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
146         blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
147         blend.colormask = PIPE_MASK_RGBA
148         ctx.set_blend(blend)
149     
150         # no-op depth/stencil/alpha
151         depth_stencil_alpha = DepthStencilAlpha()
152         ctx.set_depth_stencil_alpha(depth_stencil_alpha)
153     
154         # rasterizer
155         rasterizer = Rasterizer()
156         rasterizer.front_winding = PIPE_WINDING_CW
157         rasterizer.cull_mode = PIPE_WINDING_NONE
158         rasterizer.bypass_vs_clip_and_viewport = 1
159         ctx.set_rasterizer(rasterizer)
160     
161         # samplers
162         sampler = Sampler()
163         sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
164         sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
165         sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
166         sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
167         sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
168         sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
169         sampler.normalized_coords = 1
170         sampler.min_lod = 0
171         sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
172         ctx.set_sampler(0, sampler)
173     
174         #  texture 
175         texture = dev.texture_create(
176             target = target,
177             format = format, 
178             width = width, 
179             height = height,
180             depth = depth, 
181             last_level = last_level,
182             tex_usage = tex_usage,
183         )
184         
185         expected_rgba = FloatArray(height*width*4) 
186         texture.get_surface(
187             face = face,
188             level = level,
189             zslice = zslice,
190         ).sample_rgba(expected_rgba)
191         
192         ctx.set_sampler_texture(0, texture)
193
194         #  framebuffer 
195         cbuf_tex = dev.texture_create(
196             PIPE_FORMAT_A8R8G8B8_UNORM, 
197             width, 
198             height,
199             tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
200         )
201
202         cbuf = cbuf_tex.get_surface()
203         fb = Framebuffer()
204         fb.width = width
205         fb.height = height
206         fb.nr_cbufs = 1
207         fb.set_cbuf(0, cbuf)
208         ctx.set_framebuffer(fb)
209         rgba = FloatArray(4);
210         rgba[0] = 0.5
211         rgba[1] = 0.5
212         rgba[2] = 0.5
213         rgba[3] = 0.5
214         ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
215         del fb
216     
217         # vertex shader
218         vs = Shader('''
219             VERT1.1
220             DCL IN[0], POSITION, CONSTANT
221             DCL IN[1], GENERIC, CONSTANT
222             DCL OUT[0], POSITION, CONSTANT
223             DCL OUT[1], GENERIC, CONSTANT
224             0:MOV OUT[0], IN[0]
225             1:MOV OUT[1], IN[1]
226             2:END
227         ''')
228         #vs.dump()
229         ctx.set_vertex_shader(vs)
230     
231         # fragment shader
232         op = {
233             PIPE_TEXTURE_1D: "1D", 
234             PIPE_TEXTURE_2D: "2D", 
235             PIPE_TEXTURE_3D: "3D", 
236             PIPE_TEXTURE_CUBE: "CUBE",
237         }[target]
238         fs = Shader('''
239             FRAG1.1
240             DCL IN[0], GENERIC[0], LINEAR
241             DCL OUT[0], COLOR, CONSTANT
242             DCL SAMP[0], CONSTANT
243             0:TEX OUT[0], IN[0], SAMP[0], %s
244             1:END
245         ''' % op)
246         #fs.dump()
247         ctx.set_fragment_shader(fs)
248
249         nverts = 4
250         nattrs = 2
251         verts = FloatArray(nverts * nattrs * 4)
252     
253         x = 0
254         y = 0
255         w, h = minify((width, height), level)
256     
257         pos = [
258             [x, y],
259             [x+w, y],
260             [x+w, y+h],
261             [x, y+h],
262         ]
263     
264         tex = tex_coords(texture, face, level, zslice)
265     
266         for i in range(0, 4):
267             j = 8*i
268             verts[j + 0] = pos[i][0] # x
269             verts[j + 1] = pos[i][1] # y
270             verts[j + 2] = 0.0 # z
271             verts[j + 3] = 1.0 # w
272             verts[j + 4] = tex[i][0] # s
273             verts[j + 5] = tex[i][1] # r
274             verts[j + 6] = tex[i][2] # q
275             verts[j + 7] = 1.0
276     
277         ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
278                           nverts, 
279                           nattrs, 
280                           verts)
281     
282         ctx.flush()
283     
284         cbuf = cbuf_tex.get_surface()
285         
286         self.assert_rgba(cbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
287         
288
289
290 def main():
291     dev = Device()
292     suite = TestSuite()
293     
294     targets = [
295         PIPE_TEXTURE_2D,
296         PIPE_TEXTURE_CUBE,
297         PIPE_TEXTURE_3D,
298     ]
299     
300     formats = [
301         PIPE_FORMAT_A8R8G8B8_UNORM,
302         PIPE_FORMAT_X8R8G8B8_UNORM,
303         #PIPE_FORMAT_A8R8G8B8_SRGB,
304         PIPE_FORMAT_R5G6B5_UNORM,
305         PIPE_FORMAT_A1R5G5B5_UNORM,
306         PIPE_FORMAT_A4R4G4B4_UNORM,
307         #PIPE_FORMAT_Z32_UNORM,
308         #PIPE_FORMAT_Z24S8_UNORM,
309         #PIPE_FORMAT_Z24X8_UNORM,
310         #PIPE_FORMAT_Z16_UNORM,
311         #PIPE_FORMAT_S8_UNORM,
312         PIPE_FORMAT_A8_UNORM,
313         PIPE_FORMAT_L8_UNORM,
314         PIPE_FORMAT_YCBCR,
315         PIPE_FORMAT_DXT1_RGB,
316         #PIPE_FORMAT_DXT1_RGBA,
317         #PIPE_FORMAT_DXT3_RGBA,
318         #PIPE_FORMAT_DXT5_RGBA,
319     ]
320     
321     sizes = [64, 32, 16, 8, 4, 2, 1]
322     #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
323     #sizes = [64]
324     #sizes = [63]
325     
326     faces = [
327         PIPE_TEX_FACE_POS_X,
328         PIPE_TEX_FACE_NEG_X,
329         PIPE_TEX_FACE_POS_Y,
330         PIPE_TEX_FACE_NEG_Y, 
331         PIPE_TEX_FACE_POS_Z, 
332         PIPE_TEX_FACE_NEG_Z,
333     ]
334
335     for target in targets:
336         for format in formats:
337             for size in sizes:
338                 if target == PIPE_TEXTURE_3D:
339                     depth = size
340                 else:
341                     depth = 1
342                 for face in faces:
343                     if target != PIPE_TEXTURE_CUBE and face:
344                         continue
345                     levels = lods(size)
346                     for last_level in range(levels):
347                         for level in range(0, last_level + 1):
348                             zslice = 0
349                             while zslice < depth >> level:
350                                 test = TextureTest(
351                                     dev = dev,
352                                     target = target,
353                                     format = format, 
354                                     width = size,
355                                     height = size,
356                                     depth = depth,
357                                     last_level = last_level,
358                                     face = face,
359                                     level = level,
360                                     zslice = zslice,
361                                 )
362                                 suite.add_test(test)
363                                 zslice = (zslice + 1)*2 - 1
364     suite.run()
365
366
367 if __name__ == '__main__':
368     main()