python: Basic test case for 2d texture.
authorJosé Fonseca <jrfonseca@tungstengraphics.com>
Mon, 14 Jul 2008 13:27:40 +0000 (22:27 +0900)
committerJosé Fonseca <jrfonseca@tungstengraphics.com>
Mon, 14 Jul 2008 13:27:40 +0000 (22:27 +0900)
src/gallium/state_trackers/python/tests/base.py [new file with mode: 0644]
src/gallium/state_trackers/python/tests/data.py [new file with mode: 0644]
src/gallium/state_trackers/python/tests/texture.py [new file with mode: 0644]

diff --git a/src/gallium/state_trackers/python/tests/base.py b/src/gallium/state_trackers/python/tests/base.py
new file mode 100644 (file)
index 0000000..5778ad4
--- /dev/null
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+##########################################################################
+# 
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+# 
+##########################################################################
+
+
+from gallium import *
+
+
+# Enumerate all pixel formats
+formats = {}
+for name, value in globals().items():
+    if name.startswith("PIPE_FORMAT_") and isinstance(value, int):
+        formats[value] = name
+
+
+def save_image(filename, surface):
+    pixels = FloatArray(surface.height*surface.width*4)
+    surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels)
+
+    import Image
+    outimage = Image.new(
+        mode='RGB',
+        size=(surface.width, surface.height),
+        color=(0,0,0))
+    outpixels = outimage.load()
+    for y in range(0, surface.height):
+        for x in range(0, surface.width):
+            offset = (y*surface.width + x)*4
+            r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)]
+            outpixels[x, y] = r, g, b
+    outimage.save(filename, "PNG")
+
+
+
+class Test:
+    
+    def __init__(self):
+        pass
+    
+    def run(self):
+        raise NotImplementedError
+
+
+class TestSuite(Test):
+    
+    def __init__(self, tests = None):
+        Test.__init__(self)
+        if tests is None:
+            self.tests = []
+        else:
+            self.tests = tests
+
+    def add_test(self, test):
+        self.tests.append(test) 
+    
+    def run(self):
+        for test in self.tests:
+            self.test.run()
+
+
+class TextureTemplate:
+    
+    def __init__(self, format=PIPE_FORMAT_R8G8B8A8_UNORM, width=1, height=1, depth=1, last_level=0, target=PIPE_TEXTURE_2D):
+        self.format = format
+        self.width = width
+        self.height = height
+        self.depth = depth
+        self.last_level = last_level
+        self.target = target
+
+
+
diff --git a/src/gallium/state_trackers/python/tests/data.py b/src/gallium/state_trackers/python/tests/data.py
new file mode 100644 (file)
index 0000000..2287884
--- /dev/null
@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+##########################################################################
+# 
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+# 
+##########################################################################
+
+"""Texture data generation for use in testing."""
+
+
+import random
+
+from gallium import *
+
+
+dxt1_rgb_data = [
+    (
+        [
+            [0x99, 0xb0, 0x8e, 0xff],
+            [0x5d, 0x62, 0x89, 0xff],
+            [0x99, 0xb0, 0x8e, 0xff],
+            [0x99, 0xb0, 0x8e, 0xff],
+            [0xd6, 0xff, 0x94, 0xff],
+            [0x5d, 0x62, 0x89, 0xff],
+            [0x99, 0xb0, 0x8e, 0xff],
+            [0xd6, 0xff, 0x94, 0xff],
+            [0x5d, 0x62, 0x89, 0xff],
+            [0x5d, 0x62, 0x89, 0xff],
+            [0x99, 0xb0, 0x8e, 0xff],
+            [0x21, 0x14, 0x84, 0xff],
+            [0x5d, 0x62, 0x89, 0xff],
+            [0x21, 0x14, 0x84, 0xff],
+            [0x21, 0x14, 0x84, 0xff],
+            [0x99, 0xb0, 0x8e, 0xff],
+        ],
+        [0xf2, 0xd7, 0xb0, 0x20, 0xae, 0x2c, 0x6f, 0x97],
+    ),
+    (
+        [
+            [0xb5, 0xcf, 0x9c, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+            [0x21, 0x08, 0x6b, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+            [0x52, 0x4a, 0x7b, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+            [0xb5, 0xcf, 0x9c, 0xff],
+            [0x21, 0x08, 0x6b, 0xff],
+            [0xb5, 0xcf, 0x9c, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+            [0x52, 0x4a, 0x7b, 0xff],
+            [0xb5, 0xcf, 0x9c, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+            [0x52, 0x4a, 0x7b, 0xff],
+            [0x83, 0x8c, 0x8b, 0xff],
+        ],
+        [0x73, 0xb6, 0x4d, 0x20, 0x98, 0x2b, 0xe1, 0xb8],
+    ),
+    (
+        [
+            [0x00, 0x2c, 0xff, 0xff],
+            [0x94, 0x8d, 0x7b, 0xff],
+            [0x4a, 0x5c, 0xbd, 0xff],
+            [0x4a, 0x5c, 0xbd, 0xff],
+            [0x4a, 0x5c, 0xbd, 0xff],
+            [0x94, 0x8d, 0x7b, 0xff],
+            [0x94, 0x8d, 0x7b, 0xff],
+            [0x94, 0x8d, 0x7b, 0xff],
+            [0xde, 0xbe, 0x39, 0xff],
+            [0x94, 0x8d, 0x7b, 0xff],
+            [0xde, 0xbe, 0x39, 0xff],
+            [0xde, 0xbe, 0x39, 0xff],
+            [0xde, 0xbe, 0x39, 0xff],
+            [0xde, 0xbe, 0x39, 0xff],
+            [0xde, 0xbe, 0x39, 0xff],
+            [0x94, 0x8d, 0x7b, 0xff],
+        ],
+        [0xe7, 0xdd, 0x7f, 0x01, 0xf9, 0xab, 0x08, 0x80],
+    ),
+    (
+        [
+            [0x6b, 0x24, 0x21, 0xff],
+            [0x7b, 0x4f, 0x5d, 0xff],
+            [0x7b, 0x4f, 0x5d, 0xff],
+            [0x8b, 0x7a, 0x99, 0xff],
+            [0x7b, 0x4f, 0x5d, 0xff],
+            [0x7b, 0x4f, 0x5d, 0xff],
+            [0x6b, 0x24, 0x21, 0xff],
+            [0x8b, 0x7a, 0x99, 0xff],
+            [0x9c, 0xa6, 0xd6, 0xff],
+            [0x6b, 0x24, 0x21, 0xff],
+            [0x7b, 0x4f, 0x5d, 0xff],
+            [0x8b, 0x7a, 0x99, 0xff],
+            [0x6b, 0x24, 0x21, 0xff],
+            [0x8b, 0x7a, 0x99, 0xff],
+            [0x7b, 0x4f, 0x5d, 0xff],
+            [0x9c, 0xa6, 0xd6, 0xff],
+        ],
+        [0x3a, 0x9d, 0x24, 0x69, 0xbd, 0x9f, 0xb4, 0x39],
+    ),
+]
+
+dxt1_rgba = [
+    (
+        [
+            [0x00, 0x00, 0x00, 0x00],
+            [0x4e, 0xaa, 0x90, 0xff],
+            [0x4e, 0xaa, 0x90, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x4e, 0xaa, 0x90, 0xff],
+            [0x29, 0xff, 0xff, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x4e, 0xaa, 0x90, 0xff],
+            [0x73, 0x55, 0x21, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x4e, 0xaa, 0x90, 0xff],
+            [0x4e, 0xaa, 0x90, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x4e, 0xaa, 0x90, 0xff],
+        ],
+        [0xff, 0x2f, 0xa4, 0x72, 0xeb, 0xb2, 0xbd, 0xbe],
+    ),
+    (
+        [
+            [0xb5, 0xe3, 0x63, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x6b, 0x24, 0x84, 0xff],
+            [0xb5, 0xe3, 0x63, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0xb5, 0xe3, 0x63, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x6b, 0x24, 0x84, 0xff],
+            [0x6b, 0x24, 0x84, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0xb5, 0xe3, 0x63, 0xff],
+            [0x90, 0x83, 0x73, 0xff],
+            [0xb5, 0xe3, 0x63, 0xff],
+        ],
+        [0x30, 0x69, 0x0c, 0xb7, 0x4d, 0xf7, 0x0f, 0x67],
+    ),
+    (
+        [
+            [0x00, 0x00, 0x00, 0x00],
+            [0xc6, 0x86, 0x8c, 0xff],
+            [0xc6, 0x86, 0x8c, 0xff],
+            [0x21, 0x65, 0x42, 0xff],
+            [0x21, 0x65, 0x42, 0xff],
+            [0x21, 0x65, 0x42, 0xff],
+            [0x21, 0x65, 0x42, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x21, 0x65, 0x42, 0xff],
+            [0xc6, 0x86, 0x8c, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0xc6, 0x86, 0x8c, 0xff],
+        ],
+        [0x28, 0x23, 0x31, 0xc4, 0x17, 0xc0, 0xd3, 0x7f],
+    ),
+    (
+        [
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0xc6, 0xe3, 0x9c, 0xff],
+            [0x7b, 0x1c, 0x52, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x7b, 0x1c, 0x52, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0x7b, 0x1c, 0x52, 0xff],
+            [0xa0, 0x7f, 0x77, 0xff],
+            [0xc6, 0xe3, 0x9c, 0xff],
+            [0x00, 0x00, 0x00, 0x00],
+            [0xa0, 0x7f, 0x77, 0xff],
+        ],
+        [0xea, 0x78, 0x13, 0xc7, 0x7f, 0xfc, 0x33, 0xb6],
+    ),
+]
+
+
+
+def generate_data_compressed(surface, blocks):
+    pixels, block = blocks[0]
+    
+    stride = surface.nblocksx*surface.block.size
+    size = surface.nblocksy*stride
+
+    raw = ByteArray(size)
+    rgba = FloatArray(surface.height*surface.width*4)
+    
+    for y in range(0, surface.nblocksx):
+        for x in range(0, surface.nblocksy):
+            
+            offset = (y*surface.nblocksx + x)*surface.block.width
+            for i in range(0, surface.block.size):
+                raw[offset + i] = block[i]
+            
+            for j in range(0, surface.block.width):
+                for i in range(0, surface.block.height):
+                    offset = ((y*surface.block.height + j)*surface.width + x*surface.block.width + i)*4 
+                    pixel = pixels[j*surface.block.width + i]
+                    for ch in range(0, 4):
+                        rgba[offset + ch] = float(pixel[ch])/255.0
+    
+    surface.put_tile_raw(0, 0, surface.width, surface.height, raw, stride)
+
+    return rgba
+
+
+def generate_data_simple(surface):
+    stride = surface.nblocksx*surface.block.size
+    size = surface.nblocksy*stride
+    
+    raw = ByteArray(size)
+    rgba = FloatArray(surface.height*surface.width*4)
+    
+    for i in range(0, size):
+        raw[i] = random.randint(0, 255)
+        
+    surface.put_tile_raw(0, 0, surface.width, surface.height, raw, stride)
+    
+    surface.get_tile_rgba(0, 0, surface.width, surface.height, rgba)
+    
+    return rgba
+
+
+def generate_data(surface):
+    width = surface.width
+    height = surface.height
+    
+    if surface.format == PIPE_FORMAT_DXT1_RGB:
+        return generate_data_compressed(surface, dxt1_rgb_data)
+    if surface.format == PIPE_FORMAT_DXT1_RGBA:
+        return generate_data_compressed(surface, dxt1_rgba_data)
+    if surface.format == PIPE_FORMAT_DXT3_RGBA:
+        assert 0
+    if surface.format == PIPE_FORMAT_DXT5_RGBA:
+        assert 0
+
+    return generate_data_simple(surface)
+
+
+
diff --git a/src/gallium/state_trackers/python/tests/texture.py b/src/gallium/state_trackers/python/tests/texture.py
new file mode 100644 (file)
index 0000000..d0b6574
--- /dev/null
@@ -0,0 +1,236 @@
+#!/usr/bin/env python
+##########################################################################
+# 
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+# 
+##########################################################################
+
+
+from gallium import *
+from base import *
+from data import generate_data
+
+
+def compare_rgba(width, height, rgba1, rgba2, tol=0.01):
+    result = True
+    for y in range(0, height):
+        for x in range(0, width):
+            for ch in range(4):
+                offset = (y*width + x)*4 + ch
+                v1 = rgba1[offset]
+                v2 = rgba2[offset]
+                if abs(v1 - v2) > tol:
+                    sys.stderr.write("x=%u, y=%u, ch=%u differ: %f vs %f\n", 
+                                     x, y, ch, v1, v2)
+                    result = False
+
+
+class TextureTest(Test):
+    
+    def __init__(self, **kargs):
+        Test.__init__(self)
+        self.__dict__.update(kargs)
+
+    def run(self):
+        dev = self.dev
+        
+        format = PIPE_FORMAT_A8R8G8B8_UNORM
+        #format = PIPE_FORMAT_DXT1_RGB
+        
+        if not dev.is_format_supported(format, PIPE_TEXTURE):
+            pass
+        if not dev.is_format_supported(format, PIPE_SURFACE):
+            pass
+        
+        ctx = dev.context_create()
+    
+        width = 256
+        height = 256
+    
+        # disabled blending/masking
+        blend = Blend()
+        blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+        blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+        blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+        blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+        blend.colormask = PIPE_MASK_RGBA
+        ctx.set_blend(blend)
+    
+        # no-op depth/stencil/alpha
+        depth_stencil_alpha = DepthStencilAlpha()
+        ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+    
+        # rasterizer
+        rasterizer = Rasterizer()
+        rasterizer.front_winding = PIPE_WINDING_CW
+        rasterizer.cull_mode = PIPE_WINDING_NONE
+        rasterizer.bypass_clipping = 1
+        #rasterizer.bypass_vs = 1
+        ctx.set_rasterizer(rasterizer)
+    
+        # viewport (identity, we setup vertices in wincoords)
+        viewport = Viewport()
+        scale = FloatArray(4)
+        scale[0] = 1.0
+        scale[1] = 1.0
+        scale[2] = 1.0
+        scale[3] = 1.0
+        viewport.scale = scale
+        translate = FloatArray(4)
+        translate[0] = 0.0
+        translate[1] = 0.0
+        translate[2] = 0.0
+        translate[3] = 0.0
+        viewport.translate = translate
+        ctx.set_viewport(viewport)
+    
+        # samplers
+        sampler = Sampler()
+        sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+        sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+        sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+        sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+        sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+        sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+        sampler.normalized_coords = 1
+        ctx.set_sampler(0, sampler)
+    
+        #  texture 
+        texture = dev.texture_create(format, 
+                                     width, 
+                                     height)
+        ctx.set_sampler_texture(0, texture)
+        
+        surface = texture.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE)
+
+        expected_rgba = generate_data(surface)
+        
+        cbuf_tex = dev.texture_create(PIPE_FORMAT_A8R8G8B8_UNORM, 
+                                      width, 
+                                      height)
+
+        #  drawing dest 
+        cbuf = cbuf_tex.get_surface(usage = PIPE_BUFFER_USAGE_GPU_WRITE)
+        fb = Framebuffer()
+        fb.width = cbuf.width
+        fb.height = cbuf.height
+        fb.num_cbufs = 1
+        fb.set_cbuf(0, cbuf)
+        ctx.set_framebuffer(fb)
+    
+        # vertex shader
+        vs = Shader('''
+            VERT1.1
+            DCL IN[0], POSITION, CONSTANT
+            DCL IN[1], GENERIC, CONSTANT
+            DCL OUT[0], POSITION, CONSTANT
+            DCL OUT[1], GENERIC, CONSTANT
+            0:MOV OUT[0], IN[0]
+            1:MOV OUT[1], IN[1]
+            2:END
+        ''')
+        #vs.dump()
+        ctx.set_vertex_shader(vs)
+    
+        # fragment shader
+        fs = Shader('''
+            FRAG1.1
+            DCL IN[0], GENERIC[0], PERSPECTIVE
+            DCL OUT[0], COLOR, CONSTANT
+            DCL SAMP[0], CONSTANT
+            0:TEX OUT[0], IN[0], SAMP[0], 2D
+            1:END
+        ''')
+        fs.dump()
+        ctx.set_fragment_shader(fs)
+    
+        nverts = 4
+        nattrs = 2
+        verts = FloatArray(nverts * nattrs * 4)
+    
+        x = 0
+        y = 0
+        w = width
+        h = height
+    
+        verts[ 0] =     x # x1
+        verts[ 1] =     y # y1
+        verts[ 2] =   0.0 # z1
+        verts[ 3] =   1.0 # w1
+        verts[ 4] =   0.0 # s1
+        verts[ 5] =   0.0 # t
+        verts[ 6] =   0.0
+        verts[ 7] =   0.0
+        verts[ 8] = x + w # x2
+        verts[ 9] =     y # y2
+        verts[10] =   0.0 # z2
+        verts[11] =   1.0 # w2
+        verts[12] =   1.0 # s2
+        verts[13] =   0.0 # t2
+        verts[14] =   0.0
+        verts[15] =   0.0
+        verts[16] = x + w # x3
+        verts[17] = y + h # y3
+        verts[18] =   0.0 # z3
+        verts[19] =   1.0 # w3
+        verts[20] =   1.0 # s3
+        verts[21] =   1.0 # t3
+        verts[22] =   0.0
+        verts[23] =   0.0
+        verts[24] =     x # x4
+        verts[25] = y + h # y4
+        verts[26] =   0.0 # z4
+        verts[27] =   1.0 # w4
+        verts[28] =   0.0 # s4
+        verts[29] =   1.0 # t4
+        verts[30] =   0.0
+        verts[31] =   0.0
+    
+        ctx.surface_clear(cbuf, 0x00000000)
+        
+        ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+                          nverts, 
+                          nattrs, 
+                          verts)
+    
+        ctx.flush()
+    
+        rgba = FloatArray(surface.height*surface.width*4)
+
+        cbuf.get_tile_rgba(x, y, w, h, rgba)
+
+        compare_rgba(width, height, rgba, expected_rgba)
+        
+        #save_image("texture1.png", surface)
+        #save_image("texture2.png", cbuf)
+
+
+def main():
+    dev = Device(hardware = False)
+    test = TextureTest(dev = dev)
+    test.run()
+
+
+if __name__ == '__main__':
+    main()