Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / tests / python / tests / texture_blit.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 import random
32
33 from gallium import *
34 from base import *
35
36
37 def lods(*dims):
38 size = max(dims)
39 lods = 0
40 while size:
41 lods += 1
42 size >>= 1
43 return lods
44
45
46 def minify(dims, level = 1):
47 return [max(dim>>level, 1) for dim in dims]
48
49
50 def tex_coords(texture, face, level, zslice):
51 st = [
52 [0.0, 0.0],
53 [1.0, 0.0],
54 [1.0, 1.0],
55 [0.0, 1.0],
56 ]
57
58 if texture.target == PIPE_TEXTURE_2D:
59 return [[s, t, 0.0] for s, t in st]
60 elif texture.target == PIPE_TEXTURE_3D:
61 depth = texture.get_depth(level)
62 if depth > 1:
63 r = float(zslice)/float(depth - 1)
64 else:
65 r = 0.0
66 return [[s, t, r] for s, t in st]
67 elif texture.target == PIPE_TEXTURE_CUBE:
68 result = []
69 for s, t in st:
70 # See http://developer.nvidia.com/object/cube_map_ogl_tutorial.html
71 sc = 2.0*s - 1.0
72 tc = 2.0*t - 1.0
73 if face == PIPE_TEX_FACE_POS_X:
74 rx = 1.0
75 ry = -tc
76 rz = -sc
77 if face == PIPE_TEX_FACE_NEG_X:
78 rx = -1.0
79 ry = -tc
80 rz = sc
81 if face == PIPE_TEX_FACE_POS_Y:
82 rx = sc
83 ry = 1.0
84 rz = tc
85 if face == PIPE_TEX_FACE_NEG_Y:
86 rx = sc
87 ry = -1.0
88 rz = -tc
89 if face == PIPE_TEX_FACE_POS_Z:
90 rx = sc
91 ry = -tc
92 rz = 1.0
93 if face == PIPE_TEX_FACE_NEG_Z:
94 rx = -sc
95 ry = -tc
96 rz = -1.0
97 result.append([rx, ry, rz])
98 return result
99
100 def is_pot(n):
101 return n & (n - 1) == 0
102
103
104 class TextureColorSampleTest(TestCase):
105
106 tags = (
107 'target',
108 'format',
109 'width',
110 'height',
111 'depth',
112 'last_level',
113 'face',
114 'level',
115 'zslice',
116 )
117
118 def test(self):
119 dev = self.dev
120 ctx = self.ctx
121
122 target = self.target
123 format = self.format
124 width = self.width
125 height = self.height
126 depth = self.depth
127 last_level = self.last_level
128 face = self.face
129 level = self.level
130 zslice = self.zslice
131 minz = 0.0
132 maxz = 1.0
133
134 bind = PIPE_BIND_SAMPLER_VIEW
135 geom_flags = 0
136 if width != height:
137 geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
138 if not is_pot(width) or not is_pot(height) or not is_pot(depth):
139 geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
140
141 if not dev.is_format_supported(format, target, bind, geom_flags):
142 raise TestSkip
143
144 # disabled blending/masking
145 blend = Blend()
146 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE
147 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE
148 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
149 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
150 blend.rt[0].colormask = PIPE_MASK_RGBA
151 ctx.set_blend(blend)
152
153 # no-op depth/stencil/alpha
154 depth_stencil_alpha = DepthStencilAlpha()
155 ctx.set_depth_stencil_alpha(depth_stencil_alpha)
156
157 # rasterizer
158 rasterizer = Rasterizer()
159 rasterizer.front_winding = PIPE_WINDING_CW
160 rasterizer.cull_mode = PIPE_WINDING_NONE
161 ctx.set_rasterizer(rasterizer)
162
163 # samplers
164 sampler = Sampler()
165 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
166 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
167 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
168 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
169 sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
170 sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
171 sampler.normalized_coords = 1
172 sampler.min_lod = 0
173 sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
174 ctx.set_fragment_sampler(0, sampler)
175
176 # texture
177 texture = dev.resource_create(
178 target = target,
179 format = format,
180 width = width,
181 height = height,
182 depth = depth,
183 last_level = last_level,
184 bind = bind,
185 )
186
187 expected_rgba = FloatArray(height*width*4)
188 surface = texture.get_surface(
189 face = face,
190 level = level,
191 zslice = zslice,
192 )
193
194 ctx.surface_sample_rgba(surface, expected_rgba, True)
195
196 ctx.set_fragment_sampler_texture(0, texture)
197
198 # viewport
199 viewport = Viewport()
200 scale = FloatArray(4)
201 scale[0] = width
202 scale[1] = height
203 scale[2] = (maxz - minz) / 2.0
204 scale[3] = 1.0
205 viewport.scale = scale
206 translate = FloatArray(4)
207 translate[0] = 0.0
208 translate[1] = 0.0
209 translate[2] = (maxz - minz) / 2.0
210 translate[3] = 0.0
211 viewport.translate = translate
212 ctx.set_viewport(viewport)
213
214 # scissor
215 scissor = Scissor()
216 scissor.minx = 0
217 scissor.miny = 0
218 scissor.maxx = width
219 scissor.maxy = height
220 ctx.set_scissor(scissor)
221
222 # clip
223 clip = Clip()
224 clip.nr = 0
225 ctx.set_clip(clip)
226
227 # framebuffer
228 cbuf_tex = dev.resource_create(
229 PIPE_FORMAT_B8G8R8A8_UNORM,
230 width,
231 height,
232 bind = PIPE_BIND_RENDER_TARGET,
233 )
234
235 cbuf = cbuf_tex.get_surface()
236 fb = Framebuffer()
237 fb.width = width
238 fb.height = height
239 fb.nr_cbufs = 1
240 fb.set_cbuf(0, cbuf)
241 ctx.set_framebuffer(fb)
242 rgba = FloatArray(4);
243 rgba[0] = 0.5
244 rgba[1] = 0.5
245 rgba[2] = 0.5
246 rgba[3] = 0.5
247 ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
248 del fb
249
250 # vertex shader
251 vs = Shader('''
252 VERT
253 DCL IN[0], POSITION, CONSTANT
254 DCL IN[1], GENERIC, CONSTANT
255 DCL OUT[0], POSITION, CONSTANT
256 DCL OUT[1], GENERIC, CONSTANT
257 0:MOV OUT[0], IN[0]
258 1:MOV OUT[1], IN[1]
259 2:END
260 ''')
261 #vs.dump()
262 ctx.set_vertex_shader(vs)
263
264 # fragment shader
265 op = {
266 PIPE_TEXTURE_1D: "1D",
267 PIPE_TEXTURE_2D: "2D",
268 PIPE_TEXTURE_3D: "3D",
269 PIPE_TEXTURE_CUBE: "CUBE",
270 }[target]
271 fs = Shader('''
272 FRAG
273 DCL IN[0], GENERIC[0], LINEAR
274 DCL OUT[0], COLOR, CONSTANT
275 DCL SAMP[0], CONSTANT
276 0:TEX OUT[0], IN[0], SAMP[0], %s
277 1:END
278 ''' % op)
279 #fs.dump()
280 ctx.set_fragment_shader(fs)
281
282 nverts = 4
283 nattrs = 2
284 verts = FloatArray(nverts * nattrs * 4)
285
286 x = 0
287 y = 0
288 w, h = minify((width, height), level)
289
290 pos = [
291 [x, y],
292 [x+w, y],
293 [x+w, y+h],
294 [x, y+h],
295 ]
296
297 tex = tex_coords(texture, face, level, zslice)
298
299 for i in range(0, 4):
300 j = 8*i
301 verts[j + 0] = pos[i][0]/float(width) # x
302 verts[j + 1] = pos[i][1]/float(height) # y
303 verts[j + 2] = 0.0 # z
304 verts[j + 3] = 1.0 # w
305 verts[j + 4] = tex[i][0] # s
306 verts[j + 5] = tex[i][1] # r
307 verts[j + 6] = tex[i][2] # q
308 verts[j + 7] = 1.0
309
310 ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
311 nverts,
312 nattrs,
313 verts)
314
315 ctx.flush()
316
317 cbuf = cbuf_tex.get_surface()
318
319 self.assert_rgba(ctx, cbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
320
321
322 class TextureDepthSampleTest(TestCase):
323
324 tags = (
325 'target',
326 'format',
327 'width',
328 'height',
329 'depth',
330 'last_level',
331 'face',
332 'level',
333 'zslice',
334 )
335
336 def test(self):
337 dev = self.dev
338 ctx = self.ctx
339
340 target = self.target
341 format = self.format
342 width = self.width
343 height = self.height
344 depth = self.depth
345 last_level = self.last_level
346 face = self.face
347 level = self.level
348 zslice = self.zslice
349 minz = 0.0
350 maxz = 1.0
351
352 bind = PIPE_BIND_SAMPLER_VIEW
353 geom_flags = 0
354 if width != height:
355 geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
356 if not is_pot(width) or not is_pot(height) or not is_pot(depth):
357 geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
358
359 if not dev.is_format_supported(format, target, bind, geom_flags):
360 raise TestSkip
361
362 # disabled blending/masking
363 blend = Blend()
364 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE
365 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE
366 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
367 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
368 blend.rt[0].colormask = PIPE_MASK_RGBA
369 ctx.set_blend(blend)
370
371 # depth/stencil/alpha
372 depth_stencil_alpha = DepthStencilAlpha()
373 depth_stencil_alpha.depth.enabled = 1
374 depth_stencil_alpha.depth.writemask = 1
375 depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
376 ctx.set_depth_stencil_alpha(depth_stencil_alpha)
377
378 # rasterizer
379 rasterizer = Rasterizer()
380 rasterizer.front_winding = PIPE_WINDING_CW
381 rasterizer.cull_mode = PIPE_WINDING_NONE
382 ctx.set_rasterizer(rasterizer)
383
384 # viewport
385 viewport = Viewport()
386 scale = FloatArray(4)
387 scale[0] = width
388 scale[1] = height
389 scale[2] = (maxz - minz) / 2.0
390 scale[3] = 1.0
391 viewport.scale = scale
392 translate = FloatArray(4)
393 translate[0] = 0.0
394 translate[1] = 0.0
395 translate[2] = (maxz - minz) / 2.0
396 translate[3] = 0.0
397 viewport.translate = translate
398 ctx.set_viewport(viewport)
399
400 # samplers
401 sampler = Sampler()
402 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
403 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
404 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
405 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
406 sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
407 sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
408 sampler.normalized_coords = 1
409 sampler.min_lod = 0
410 sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
411 ctx.set_fragment_sampler(0, sampler)
412
413 # texture
414 texture = dev.resource_create(
415 target = target,
416 format = format,
417 width = width,
418 height = height,
419 depth = depth,
420 last_level = last_level,
421 bind = bind,
422 )
423
424 expected_rgba = FloatArray(height*width*4)
425 surface = texture.get_surface(
426 face = face,
427 level = level,
428 zslice = zslice,
429 )
430
431 ctx.surface_sample_rgba(surface, expected_rgba, True)
432
433 ctx.set_fragment_sampler_texture(0, texture)
434
435 # scissor
436 scissor = Scissor()
437 scissor.minx = 0
438 scissor.miny = 0
439 scissor.maxx = width
440 scissor.maxy = height
441 ctx.set_scissor(scissor)
442
443 # clip
444 clip = Clip()
445 clip.nr = 0
446 ctx.set_clip(clip)
447
448 # framebuffer
449 cbuf_tex = dev.resource_create(
450 PIPE_FORMAT_B8G8R8A8_UNORM,
451 width,
452 height,
453 bind = PIPE_BIND_RENDER_TARGET,
454 )
455
456 zsbuf_tex = dev.resource_create(
457 PIPE_FORMAT_X8Z24_UNORM,
458 width,
459 height,
460 bind = PIPE_BIND_RENDER_TARGET,
461 )
462
463 cbuf = cbuf_tex.get_surface()
464 zsbuf = zsbuf_tex.get_surface()
465 fb = Framebuffer()
466 fb.width = width
467 fb.height = height
468 fb.nr_cbufs = 1
469 fb.set_cbuf(0, cbuf)
470 fb.set_zsbuf(zsbuf)
471 ctx.set_framebuffer(fb)
472 rgba = FloatArray(4);
473 rgba[0] = 0.5
474 rgba[1] = 0.5
475 rgba[2] = 0.5
476 rgba[3] = 0.5
477 ctx.clear(PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0)
478 del fb
479
480 # vertex shader
481 vs = Shader('''
482 VERT
483 DCL IN[0], POSITION, CONSTANT
484 DCL IN[1], GENERIC, CONSTANT
485 DCL OUT[0], POSITION, CONSTANT
486 DCL OUT[1], GENERIC, CONSTANT
487 0:MOV OUT[0], IN[0]
488 1:MOV OUT[1], IN[1]
489 2:END
490 ''')
491 #vs.dump()
492 ctx.set_vertex_shader(vs)
493
494 # fragment shader
495 op = {
496 PIPE_TEXTURE_1D: "1D",
497 PIPE_TEXTURE_2D: "2D",
498 PIPE_TEXTURE_3D: "3D",
499 PIPE_TEXTURE_CUBE: "CUBE",
500 }[target]
501 fs = Shader('''
502 FRAG
503 DCL IN[0], GENERIC[0], LINEAR
504 DCL SAMP[0], CONSTANT
505 DCL OUT[0].z, POSITION
506 0:TEX OUT[0].z, IN[0], SAMP[0], %s
507 1:END
508 ''' % op)
509 #fs.dump()
510 ctx.set_fragment_shader(fs)
511
512 nverts = 4
513 nattrs = 2
514 verts = FloatArray(nverts * nattrs * 4)
515
516 x = 0
517 y = 0
518 w, h = minify((width, height), level)
519
520 pos = [
521 [x, y],
522 [x+w, y],
523 [x+w, y+h],
524 [x, y+h],
525 ]
526
527 tex = tex_coords(texture, face, level, zslice)
528
529 for i in range(0, 4):
530 j = 8*i
531 verts[j + 0] = pos[i][0]/float(width) # x
532 verts[j + 1] = pos[i][1]/float(height) # y
533 verts[j + 2] = 0.0 # z
534 verts[j + 3] = 1.0 # w
535 verts[j + 4] = tex[i][0] # s
536 verts[j + 5] = tex[i][1] # r
537 verts[j + 6] = tex[i][2] # q
538 verts[j + 7] = 1.0
539
540 ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
541 nverts,
542 nattrs,
543 verts)
544
545 ctx.flush()
546
547 zsbuf = zsbuf_tex.get_surface()
548
549 self.assert_rgba(ctx, zsbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
550
551
552
553
554 def main():
555 random.seed(0xdead3eef)
556
557 dev = Device()
558 ctx = dev.context_create()
559 suite = TestSuite()
560
561 targets = [
562 PIPE_TEXTURE_2D,
563 PIPE_TEXTURE_CUBE,
564 PIPE_TEXTURE_3D,
565 ]
566
567 #sizes = [64, 32, 16, 8, 4, 2, 1]
568 #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
569 sizes = [64]
570 #sizes = [63]
571
572 faces = [
573 PIPE_TEX_FACE_POS_X,
574 PIPE_TEX_FACE_NEG_X,
575 PIPE_TEX_FACE_POS_Y,
576 PIPE_TEX_FACE_NEG_Y,
577 PIPE_TEX_FACE_POS_Z,
578 PIPE_TEX_FACE_NEG_Z,
579 ]
580
581 try:
582 n = int(sys.argv[1])
583 except:
584 n = 10000
585
586 for i in range(n):
587 format = random.choice(formats.keys())
588 if not util_format_is_depth_or_stencil(format):
589 is_depth_or_stencil = util_format_is_depth_or_stencil(format)
590
591 if is_depth_or_stencil:
592 target = PIPE_TEXTURE_2D
593 else:
594 target = random.choice(targets)
595
596 size = random.choice(sizes)
597
598 if target == PIPE_TEXTURE_3D:
599 depth = size
600 else:
601 depth = 1
602
603 if target == PIPE_TEXTURE_CUBE:
604 face = random.choice(faces)
605 else:
606 face = PIPE_TEX_FACE_POS_X
607
608 levels = lods(size)
609 last_level = random.randint(0, levels - 1)
610 level = random.randint(0, last_level)
611 zslice = random.randint(0, max(depth >> level, 1) - 1)
612
613 if is_depth_or_stencil:
614 klass = TextureDepthSampleTest
615 else:
616 klass = TextureColorSampleTest
617
618 test = klass(
619 dev = dev,
620 ctx = ctx,
621 target = target,
622 format = format,
623 width = size,
624 height = size,
625 depth = depth,
626 last_level = last_level,
627 face = face,
628 level = level,
629 zslice = zslice,
630 )
631 suite.add_test(test)
632 suite.run()
633
634
635 if __name__ == '__main__':
636 main()