gallium: support for array textures and related changes

resources have a array_size parameter now.
get_tex_surface and tex_surface_destroy have been renamed to create_surface
and surface_destroy and moved to context, similar to sampler views (and
create_surface now uses a template just like create_sampler_view). Surfaces
now really should only be used for rendering. In particular they shouldn't be
used as some kind of 2d abstraction for sharing a texture. offset/layout fields
don't make sense any longer and have been removed, width/height should go too.
surfaces and sampler views now specify a layer range (for texture resources),
layer is either array slice, depth slice or cube face.
pipe_subresource is gone array slices (or cube faces) are now treated the same
as depth slices in transfers etc. (that is, they use the z coord of the
respective functions).

Squashed commit of the following:

commit a45bd509014743d21a532194d7b658a1aeb00cb7
Merge: 1aeca28 32e1e59
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Dec 2 04:32:06 2010 +0100

    Merge remote branch 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/drivers/i915/i915_resource_texture.c
    	src/gallium/drivers/i915/i915_state_emit.c
    	src/gallium/drivers/i915/i915_surface.c

commit 1aeca287a827f29206078fa1204715a477072c08
Merge: 912f042 6f7c8c3
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Dec 2 00:37:11 2010 +0100

    Merge remote branch 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/state_trackers/vega/api_filters.c
    	src/gallium/state_trackers/vega/api_images.c
    	src/gallium/state_trackers/vega/mask.c
    	src/gallium/state_trackers/vega/paint.c
    	src/gallium/state_trackers/vega/renderer.c
    	src/gallium/state_trackers/vega/st_inlines.h
    	src/gallium/state_trackers/vega/vg_context.c
    	src/gallium/state_trackers/vega/vg_manager.c

commit 912f042e1d439de17b36be9a740358c876fcd144
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Dec 1 03:01:55 2010 +0100

    gallium: even more compile fixes after merge

commit 6fc95a58866d2a291def333608ba9c10c3f07e82
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Dec 1 00:22:26 2010 +0100

    gallium: some fixes after merge

commit a8d5ffaeb5397ffaa12fb422e4e7efdf0494c3e2
Merge: f7a202f 2da02e7
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Tue Nov 30 23:41:26 2010 +0100

    Merge remote branch 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/drivers/i915/i915_state_emit.c
    	src/gallium/state_trackers/vega/api_images.c
    	src/gallium/state_trackers/vega/vg_context.c

commit f7a202fde2aea2ec78ef58830f945a5e214e56ab
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Nov 24 19:19:32 2010 +0100

    gallium: even more fixes/cleanups after merge

commit 6895a7f969ed7f9fa8ceb788810df8dbcf04c4c9
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Nov 24 03:07:36 2010 +0100

    gallium: more compile fixes after merge

commit af0501a5103b9756bc4d79167bd81051ad6e8670
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Tue Nov 23 19:24:45 2010 +0100

    gallium: lots of compile fixes after merge

commit 0332003c2feb60f2a20e9a40368180c4ecd33e6b
Merge: 26c6346 b6b91fa
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Tue Nov 23 17:02:26 2010 +0100

    Merge remote branch 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/auxiliary/gallivm/lp_bld_sample.c
    	src/gallium/auxiliary/util/u_blit.c
    	src/gallium/auxiliary/util/u_blitter.c
    	src/gallium/auxiliary/util/u_inlines.h
    	src/gallium/auxiliary/util/u_surface.c
    	src/gallium/auxiliary/util/u_surfaces.c
    	src/gallium/docs/source/context.rst
    	src/gallium/drivers/llvmpipe/lp_rast.c
    	src/gallium/drivers/nv50/nv50_state_validate.c
    	src/gallium/drivers/nvfx/nv04_surface_2d.c
    	src/gallium/drivers/nvfx/nv04_surface_2d.h
    	src/gallium/drivers/nvfx/nvfx_buffer.c
    	src/gallium/drivers/nvfx/nvfx_miptree.c
    	src/gallium/drivers/nvfx/nvfx_resource.c
    	src/gallium/drivers/nvfx/nvfx_resource.h
    	src/gallium/drivers/nvfx/nvfx_state_fb.c
    	src/gallium/drivers/nvfx/nvfx_surface.c
    	src/gallium/drivers/nvfx/nvfx_transfer.c
    	src/gallium/drivers/r300/r300_state_derived.c
    	src/gallium/drivers/r300/r300_texture.c
    	src/gallium/drivers/r600/r600_blit.c
    	src/gallium/drivers/r600/r600_buffer.c
    	src/gallium/drivers/r600/r600_context.h
    	src/gallium/drivers/r600/r600_screen.c
    	src/gallium/drivers/r600/r600_screen.h
    	src/gallium/drivers/r600/r600_state.c
    	src/gallium/drivers/r600/r600_texture.c
    	src/gallium/include/pipe/p_defines.h
    	src/gallium/state_trackers/egl/common/egl_g3d_api.c
    	src/gallium/state_trackers/glx/xlib/xm_st.c
    	src/gallium/targets/libgl-gdi/gdi_softpipe_winsys.c
    	src/gallium/targets/libgl-gdi/libgl_gdi.c
    	src/gallium/tests/graw/tri.c
    	src/mesa/state_tracker/st_cb_blit.c
    	src/mesa/state_tracker/st_cb_readpixels.c

commit 26c6346b385929fba94775f33838d0cceaaf1127
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Mon Aug 2 19:37:21 2010 +0200

    fix more merge breakage

commit b30d87c6025eefe7f6979ffa8e369bbe755d5c1d
Merge: 9461bf3 1f1928d
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Mon Aug 2 19:15:38 2010 +0200

    Merge remote branch 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/drivers/llvmpipe/lp_rast.c
    	src/gallium/drivers/llvmpipe/lp_rast_priv.h
    	src/gallium/drivers/r300/r300_blit.c
    	src/gallium/drivers/r300/r300_screen_buffer.c
    	src/gallium/drivers/r300/r300_state_derived.c
    	src/gallium/drivers/r300/r300_texture.c
    	src/gallium/drivers/r300/r300_texture.h
    	src/gallium/drivers/r300/r300_transfer.c
    	src/gallium/drivers/r600/r600_screen.c
    	src/gallium/drivers/r600/r600_state.c
    	src/gallium/drivers/r600/r600_texture.c
    	src/gallium/drivers/r600/r600_texture.h
    	src/gallium/state_trackers/dri/common/dri1_helper.c
    	src/gallium/state_trackers/dri/sw/drisw.c
    	src/gallium/state_trackers/xorg/xorg_exa.c

commit 9461bf3cfb647d2301364ae29fc3084fff52862a
Merge: 17492d7 0eaccb3
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Jul 15 20:13:45 2010 +0200

    Merge commit 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/auxiliary/util/u_blitter.c
    	src/gallium/drivers/llvmpipe/lp_rast.c
    	src/gallium/drivers/llvmpipe/lp_surface.c
    	src/gallium/drivers/r300/r300_render.c
    	src/gallium/drivers/r300/r300_state.c
    	src/gallium/drivers/r300/r300_texture.c
    	src/gallium/drivers/r300/r300_transfer.c
    	src/gallium/tests/trivial/quad-tex.c

commit 17492d705e7b7f607b71db045c3bf344cb6842b3
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Fri Jun 18 10:58:08 2010 +0100

    gallium: rename element_offset/width fields in views to first/last_element

    This is much more consistent with the other fields used there
    (first/last level, first/last layer).
    Actually thinking about removing the ugly union/structs again and
    rename first/last_layer to something even more generic which could also
    be used for buffers (like first/last_member) without inducing headaches.

commit 1b717a289299f942de834dcccafbab91361e20ab
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Jun 17 14:46:09 2010 +0100

    gallium: remove PIPE_SURFACE_LAYOUT_LINEAR definition

    This was only used by the layout field of pipe_surface, but this
    driver internal stuff is gone so there's no need for this driver independent
    layout definition neither.

commit 10cb644b31b3ef47e6c7b55e514ad24bb891fac4
Merge: 5691db9 c85971d
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Jun 17 12:20:41 2010 +0100

    Merge commit 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/docs/source/glossary.rst
    	src/gallium/tests/graw/fs-test.c
    	src/gallium/tests/graw/gs-test.c

commit 5691db960ca3d525ce7d6c32d9c7a28f5e907f3b
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Jun 17 11:29:03 2010 +0100

    st/wgl: fix interface changes bugs

commit 2303ec32143d363b46e59e4b7c91b0ebd34a16b2
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Jun 16 19:42:32 2010 +0100

    gallium: adapt code to interface changes...

commit dcae4f586f0d0885b72674a355e5d56d47afe77d
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Jun 16 19:42:05 2010 +0100

    gallium: separate depth0 and array_size in the resource itself.

    These fields are still mutually exclusive (since no 3d array textures exist)
    but it ultimately seemed to error-prone to adapt all code accept the new
    meaning of depth0 (drivers stick that into hardware regs, calculate mipmap
    sizes etc.). And it isn't really cleaner anyway.
    So, array textures will have depth0 of 1, but instead use array_size,
    3D textures will continue to use depth0 (and have array_size of 1). Cube
    maps also will use array_size to indicate their 6 faces, but since all drivers
    should just be fine by inferring this themselves from the fact it's a cube map
    as they always used to nothing should break.

commit 621737a638d187d208712250fc19a91978fdea6b
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Jun 16 17:47:38 2010 +0100

    gallium: adapt code to interface changes

    There are still usages of pipe_surface where pipe_resource should be used,
    which should eventually be fixed.

commit 2d17f5efe166b2c3d51957c76294165ab30b8ae2
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Wed Jun 16 17:46:14 2010 +0100

    gallium: more interface changes

    In particular to enable usage of buffers in views, and ability to use a
    different pipe_format in pipe_surface.
    Get rid of layout and offset parameter in pipe_surface - the former was
    not used in any (public) code anyway, and the latter should either be computed
    on-demand or driver can use subclass of pipe_surface.
    Also make create_surface() use a template to be more consistent with
    other functions.

commit 71f885ee16aa5cf2742c44bfaf0dc5b8734b9901
Merge: 3232d11 8ad410d
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Mon Jun 14 14:19:51 2010 +0100

    Merge commit 'origin/master' into gallium-array-textures

    Conflicts:
    	src/gallium/auxiliary/util/u_box.h
    	src/gallium/drivers/nv50/nv50_surface.c
    	src/gallium/drivers/nvfx/nvfx_surface.c
    	src/gallium/drivers/r300/r300_blit.c
    	src/gallium/drivers/r300/r300_texture.c
    	src/gallium/drivers/r300/r300_transfer.c
    	src/gallium/drivers/r600/r600_blit.c
    	src/gallium/drivers/r600/r600_screen.h
    	src/gallium/include/pipe/p_state.h

commit 3232d11fe3ebf7686286013c357b404714853984
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Mon Jun 14 11:40:04 2010 +0100

    mesa/st: adapt to interface changes

    still need to fix pipe_surface sharing
    (as that is now per-context).
    Also broken is depth0 handling - half the code assumes
    this is also used for array textures (and hence by extension
    of that cube maps would have depth 6), half the code does not...

commit f433b7f7f552720e5eade0b4078db94590ee85e1
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Mon Jun 14 11:35:52 2010 +0100

    gallium: fix a couple of bugs in interface chnage fixes

commit 818366b28ea18f514dc791646248ce6f08d9bbcf
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:42:11 2010 +0200

    targets: adapt to interface changes

    Yes even that needs adjustments...

commit 66c511ab1682c9918e0200902039247793acb41e
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:41:13 2010 +0200

    tests: adapt to interface changes

    Everything needs to be fixed :-(.

commit 6b494635d9dbdaa7605bc87b1ebf682b138c5808
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:39:50 2010 +0200

    st: adapt non-rendering state trackers to interface changes

    might not be quite right in all places, but they really don't want
    to use pipe_surface.

commit 00c4289a35d86e4fe85919ec32aa9f5ffe69d16d
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:38:48 2010 +0200

    winsys: adapt to interface changes

commit 39d858554dc9ed5dbc795626fec3ef9deae552a0
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:26:54 2010 +0200

    st/python: adapt to interface changes

    don't think that will work, sorry.

commit 6e9336bc49b32139cec4e683857d0958000e15e3
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:26:07 2010 +0200

    st/vega: adapt to interface changes

commit e07f2ae9aaf8842757d5d50865f76f8276245e11
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:25:56 2010 +0200

    st/xorg: adapt to interface changes

commit 05531c10a74a4358103e30d3b38a5eceb25c947f
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:24:53 2010 +0200

    nv50: adapt to interface changes

commit 97704f388d7042121c6d496ba8c003afa3ea2bf3
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:24:45 2010 +0200

    nvfx: adapt to interface changes

commit a8a9c93d703af6e8f5c12e1cea9ec665add1abe0
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:24:01 2010 +0200

    i965g: adapt to interface changes

commit 0dde209589872d20cc34ed0b237e3ed7ae0e2de3
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:22:38 2010 +0200

    i915g: adapt to interface changes

commit 5cac9beede69d12f5807ee1a247a4c864652799e
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:20:58 2010 +0200

    svga: adapt to interface changes

    resource_copy_region still looking fishy.
    Was not very suited to unified zslice/face approach...

commit 08b5a6af4b963a3e4c75fc336bf6c0772dce5150
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:20:01 2010 +0200

    rbug: adapt to interface changes

    Not sure if that won't need changes elsewhere?

commit c9fd24b1f586bcef2e0a6e76b68e40fca3408964
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:19:31 2010 +0200

    trace: adapt to interface changes

commit ed84e010afc5635a1a47390b32247a266f65b8d1
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:19:21 2010 +0200

    failover: adapt to interface changes

commit a1d4b4a293da933276908e3393435ec4b43cf201
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:19:12 2010 +0200

    identity: adapt to interface changes

commit a8dd73e2c56c7d95ffcf174408f38f4f35fd2f4c
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:18:55 2010 +0200

    softpipe: adapt to interface changes

commit a886085893e461e8473978e8206ec2312b7077ff
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:18:44 2010 +0200

    llvmpipe: adapt to interface changes

commit 70523f6d567d8b7cfda682157556370fd3c43460
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:18:14 2010 +0200

    r600g: adapt to interface changes

commit 3f4bc72bd80994865eb9f6b8dfd11e2b97060d19
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:18:05 2010 +0200

    r300g: adapt to interface changes

commit 5d353b55ee14db0ac0515b5a3cf9389430832c19
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:17:37 2010 +0200

    cell: adapt to interface changes

    not even compile tested

commit cf5d03601322c2dcb12d7a9c2f1745e2b2a35eb4
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:14:59 2010 +0200

    util: adapt to interface changes

    amazing how much code changes just due to some subtle interface changes?

commit dc98d713c6937c0e177fc2caf23020402cc7ea7b
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Sat Jun 12 02:12:40 2010 +0200

    gallium: more interface fail, docs

    this also changes flush_frontbuffer to use a pipe_resource instead of
    a pipe_surface - pipe_surface is not meant to be (or at least no longer)
    an abstraction for standalone 2d images which get passed around.
    (This has also implications for the non-rendering state-trackers.)

commit 08436d27ddd59857c22827c609b692aa0c407b7b
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Jun 10 17:42:52 2010 +0200

    gallium: fix array texture interface changes bugs, docs

commit 4a4d927609b62b4d7fb9dffa35158afe282f277b
Author: Roland Scheidegger <sroland@vmware.com>
Date:   Thu Jun 3 22:02:44 2010 +0200

    gallium: interface changes for array textures and related cleanups

    This patch introduces array textures to gallium (note they are not immediately
    usable without the associated changes to the shader side).
    Also, this abandons pipe_subresource in favor of using level and layer
    parameters since the distinction between several faces (which was part of
    pipe_subresource for cube textures) and several z slices (which were not part
    of pipe_subresource but instead part of pipe_box where appropriate for 3d
    textures) is gone at the resource level.
    Textures, be it array, cube, or 3d, now use a "unified" set of parameters,
    there is no distinction between array members, cube faces, or 3d zslices.
    This is unlike d3d10, whose subresource index includes layer information for
    array textures, but which considers all z slices of a 3d texture to be part
    of the same subresource.
    In contrast to d3d10, OpenGL though reuses old 2d and 3d function entry points
    for 1d and 2d array textures, respectively, which also implies that for instance
    it is possible to specify all layers of a 2d array texture at once (note that
    this is not possible for cube maps, which use the 2d entry points, although
    it is possible for cube map arrays, which aren't supported yet in gallium).
    This should possibly make drivers a bit simpler, and also get rid of mutually
    exclusive parameters in some functions (as z and face were exclusive), one
    potential downside would be that 3d array textures could not easily be supported
    without reverting this, but those are nowhere to be seen.

    Also along with adjusting to new parameters, rename get_tex_surface /
    tex_surface_destroy to create_surface / surface_destroy and move them from
    screen to context, which reflects much better what those do (they are analogous
    to create_sampler_view / sampler_view_destroy).

    PIPE_CAP_ARRAY_TEXTURES is used to indicate if a driver supports all of this
    functionality (that is, both sampling from array texture as well as use a range
    of layers as a render target, with selecting the layer from the geometry shader).
diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
index d1aba76..0851b9a 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c
@@ -406,6 +406,7 @@
    texTemp.width0 = 1 << MAX_TEXTURE_LEVEL;
    texTemp.height0 = 1 << MAX_TEXTURE_LEVEL;
    texTemp.depth0 = 1;
+   texTemp.array_size = 1;
    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
    aaline->texture = screen->resource_create(screen, &texTemp);
@@ -441,10 +442,10 @@
       /* This texture is new, no need to flush. 
        */
       transfer = pipe->get_transfer(pipe,
-				    aaline->texture,
-				    u_subresource(0, level), 
-				    PIPE_TRANSFER_WRITE,
-				    &box);
+                                    aaline->texture,
+                                    level,
+                                    PIPE_TRANSFER_WRITE,
+                                    &box);
 
       data = pipe->transfer_map(pipe, transfer);
       if (data == NULL)
diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
index ed9a53e..f5515c1 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c
@@ -393,8 +393,8 @@
     */
    pipe->flush( pipe, PIPE_FLUSH_TEXTURE_CACHE, NULL );
 
-   transfer = pipe_get_transfer(pipe, pstip->texture, 0, 0, 0,
-				    PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
+   transfer = pipe_get_transfer(pipe, pstip->texture, 0, 0,
+                                PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
    data = pipe->transfer_map(pipe, transfer);
 
    /*
@@ -440,6 +440,7 @@
    texTemp.width0 = 32;
    texTemp.height0 = 32;
    texTemp.depth0 = 1;
+   texTemp.array_size = 1;
    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
    pstip->texture = screen->resource_create(screen, &texTemp);
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
index 771095f..4a7fe69 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
@@ -134,7 +134,7 @@
    state->min_img_filter    = sampler->min_img_filter;
    state->mag_img_filter    = sampler->mag_img_filter;
 
-   if (view->last_level && sampler->max_lod > 0.0f) {
+   if (view->u.tex.last_level && sampler->max_lod > 0.0f) {
       state->min_mip_filter = sampler->min_mip_filter;
    } else {
       state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
@@ -155,7 +155,7 @@
             state->apply_min_lod = 1;
          }
 
-         if (sampler->max_lod < (float)view->last_level) {
+         if (sampler->max_lod < (float)view->u.tex.last_level) {
             state->apply_max_lod = 1;
          }
       }
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index 9e70aa2..c11f7d3 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -291,7 +291,7 @@
 void
 util_blit_pixels_writemask(struct blit_state *ctx,
                            struct pipe_resource *src_tex,
-                           struct pipe_subresource srcsub,
+                           unsigned src_level,
                            int srcX0, int srcY0,
                            int srcX1, int srcY1,
                            int srcZ0,
@@ -316,13 +316,12 @@
    assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
           filter == PIPE_TEX_MIPFILTER_LINEAR);
 
-   assert(srcsub.level <= src_tex->last_level);
+   assert(src_level <= src_tex->last_level);
 
    /* do the regions overlap? */
    overlap = src_tex == dst->texture &&
-             dst->face == srcsub.face &&
-             dst->level == srcsub.level &&
-             dst->zslice == srcZ0 &&
+             dst->u.tex.level == src_level &&
+             dst->u.tex.first_layer == srcZ0 &&
       regions_overlap(srcX0, srcY0, srcX1, srcY1,
                       dstX0, dstY0, dstX1, dstY1);
 
@@ -339,16 +338,19 @@
        (dstX1 - dstX0) == (srcX1 - srcX0) &&
        (dstY1 - dstY0) == (srcY1 - srcY0) &&
        !overlap) {
-      struct pipe_subresource subdst;
-      subdst.face = dst->face;
-      subdst.level = dst->level;
+      struct pipe_box src_box;
+      src_box.x = srcX0;
+      src_box.y = srcY0;
+      src_box.z = srcZ0;
+      src_box.width = srcW;
+      src_box.height = srcH;
+      src_box.depth = 1;
       pipe->resource_copy_region(pipe,
-                                 dst->texture, subdst,
-                                 dstX0, dstY0, dst->zslice,/* dest */
-                                 src_tex, srcsub,
-                                 srcX0, srcY0, srcZ0,/* src */
-                                 srcW, srcH);       /* size */
-      return;
+                                 dst->texture, dst->u.tex.level,
+                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
+                                 src_tex, src_level,
+                                 &src_box);
+       return;
    }
 
    /* Create a temporary texture when src and dest alias or when src
@@ -359,16 +361,16 @@
     * This can still be improved upon.
     */
    if ((src_tex == dst->texture &&
-       dst->face == srcsub.face &&
-       dst->level == srcsub.level &&
-       dst->zslice == srcZ0) ||
+       dst->u.tex.level == src_level &&
+       dst->u.tex.first_layer == srcZ0) ||
        (src_tex->target != PIPE_TEXTURE_2D &&
+       src_tex->target != PIPE_TEXTURE_2D &&
        src_tex->target != PIPE_TEXTURE_RECT))
    {
       struct pipe_resource texTemp;
       struct pipe_resource *tex;
       struct pipe_sampler_view sv_templ;
-      struct pipe_subresource texsub;
+      struct pipe_box src_box;
       const int srcLeft = MIN2(srcX0, srcX1);
       const int srcTop = MIN2(srcY0, srcY1);
 
@@ -394,19 +396,23 @@
       texTemp.width0 = srcW;
       texTemp.height0 = srcH;
       texTemp.depth0 = 1;
+      texTemp.array_size = 1;
       texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
       tex = screen->resource_create(screen, &texTemp);
       if (!tex)
          return;
 
-      texsub.face = 0;
-      texsub.level = 0;
+      src_box.x = srcLeft;
+      src_box.y = srcTop;
+      src_box.z = srcZ0;
+      src_box.width = srcW;
+      src_box.height = srcH;
+      src_box.depth = 1;
       /* load temp texture */
       pipe->resource_copy_region(pipe,
-                                 tex, texsub, 0, 0, 0,  /* dest */
-                                 src_tex, srcsub, srcLeft, srcTop, srcZ0, /* src */
-                                 srcW, srcH);     /* size */
+                                 tex, 0, 0, 0, 0,  /* dest */
+                                 src_tex, src_level, &src_box);
 
       normalized = tex->target != PIPE_TEXTURE_RECT;
       if(normalized) {
@@ -433,7 +439,6 @@
    }
    else {
       u_sampler_view_default_template(&sv_templ, src_tex, src_tex->format);
-      sv_templ.first_level = sv_templ.last_level = srcsub.level;
       sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
 
       if (!sampler_view) {
@@ -447,10 +452,10 @@
       normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
       if(normalized)
       {
-         s0 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
-         s1 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
-         t0 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
-         t1 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
+         s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
+         s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
+         t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
+         t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
       }
    }
 
@@ -489,9 +494,8 @@
    ctx->sampler.normalized_coords = normalized;
    ctx->sampler.min_img_filter = filter;
    ctx->sampler.mag_img_filter = filter;
-   /* we've limited this already with the sampler view but you never know... */
-   ctx->sampler.min_lod = srcsub.level;
-   ctx->sampler.max_lod = srcsub.level;
+   ctx->sampler.min_lod = src_level;
+   ctx->sampler.max_lod = src_level;
    cso_single_sampler(ctx->cso, 0, &ctx->sampler);
    cso_single_sampler_done(ctx->cso);
 
@@ -575,7 +579,7 @@
 void
 util_blit_pixels(struct blit_state *ctx,
                  struct pipe_resource *src_tex,
-                 struct pipe_subresource srcsub,
+                 unsigned src_level,
                  int srcX0, int srcY0,
                  int srcX1, int srcY1,
                  int srcZ,
@@ -585,7 +589,7 @@
                  float z, uint filter )
 {
    util_blit_pixels_writemask( ctx, src_tex,
-                               srcsub,
+                               src_level,
                                srcX0, srcY0,
                                srcX1, srcY1,
                                srcZ,
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
index b8a0dfc..3009e25 100644
--- a/src/gallium/auxiliary/util/u_blit.h
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -42,7 +42,6 @@
 struct pipe_context;
 struct pipe_resource;
 struct pipe_sampler_view;
-struct pipe_subresource;
 struct pipe_surface;
 
 
@@ -55,7 +54,7 @@
 extern void
 util_blit_pixels(struct blit_state *ctx,
                  struct pipe_resource *src_tex,
-                 struct pipe_subresource srcsub,
+                 unsigned src_level,
                  int srcX0, int srcY0,
                  int srcX1, int srcY1,
                  int srcZ0,
@@ -67,7 +66,7 @@
 void
 util_blit_pixels_writemask(struct blit_state *ctx,
                            struct pipe_resource *src_tex,
-                           struct pipe_subresource srcsub,
+                           unsigned src_level,
                            int srcX0, int srcY0,
                            int srcX1, int srcY1,
                            int srcZ0,
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index bd9e65f..eeed87e 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -409,17 +409,17 @@
 }
 
 static void get_texcoords(struct pipe_resource *src,
-                                     struct pipe_subresource subsrc,
-                                     unsigned x1, unsigned y1,
-                                     unsigned x2, unsigned y2,
-                                     boolean normalized, float out[4])
+                          unsigned level,
+                          unsigned x1, unsigned y1,
+                          unsigned x2, unsigned y2,
+                          boolean normalized, float out[4])
 {
    if(normalized)
    {
-      out[0] = x1 / (float)u_minify(src->width0,  subsrc.level);
-      out[1] = y1 / (float)u_minify(src->height0, subsrc.level);
-      out[2] = x2 / (float)u_minify(src->width0,  subsrc.level);
-      out[3] = y2 / (float)u_minify(src->height0, subsrc.level);
+      out[0] = x1 / (float)u_minify(src->width0,  level);
+      out[1] = y1 / (float)u_minify(src->height0, level);
+      out[2] = x2 / (float)u_minify(src->width0,  level);
+      out[3] = y2 / (float)u_minify(src->height0, level);
    }
    else
    {
@@ -448,14 +448,14 @@
 
 static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
                                      struct pipe_resource *src,
-                                     struct pipe_subresource subsrc,
+                                     unsigned level,
                                      unsigned x1, unsigned y1,
                                      unsigned x2, unsigned y2)
 {
    unsigned i;
    float coord[4];
 
-   get_texcoords(src, subsrc, x1, y1, x2, y2, TRUE, coord);
+   get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord);
    set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
 
    for (i = 0; i < 4; i++) {
@@ -466,15 +466,15 @@
 
 static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx,
                                      struct pipe_resource *src,
-                                     struct pipe_subresource subsrc,
+                                     unsigned level,
                                      unsigned zslice,
                                      unsigned x1, unsigned y1,
                                      unsigned x2, unsigned y2)
 {
    int i;
-   float r = zslice / (float)u_minify(src->depth0, subsrc.level);
+   float r = zslice / (float)u_minify(src->depth0, level);
 
-   blitter_set_texcoords_2d(ctx, src, subsrc, x1, y1, x2, y2);
+   blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2);
 
    for (i = 0; i < 4; i++)
       ctx->vertices[i][1][2] = r; /*r*/
@@ -482,7 +482,7 @@
 
 static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
                                        struct pipe_resource *src,
-                                       struct pipe_subresource subsrc,
+                                       unsigned level, unsigned face,
                                        unsigned x1, unsigned y1,
                                        unsigned x2, unsigned y2)
 {
@@ -490,10 +490,10 @@
    float coord[4];
    float st[4][2];
 
-   get_texcoords(src, subsrc, x1, y1, x2, y2, TRUE, coord);
+   get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord);
    set_texcoords_in_vertices(coord, &st[0][0], 2);
 
-   util_map_texcoords2d_onto_cubemap(subsrc.face,
+   util_map_texcoords2d_onto_cubemap(face,
                                      /* pointer, stride in floats */
                                      &st[0][0], 2,
                                      &ctx->vertices[0][1][0], 8);
@@ -516,7 +516,7 @@
 
    /* write vertices and draw them */
    u_box_1d(0, sizeof(ctx->vertices), &box);
-   pipe->transfer_inline_write(pipe, ctx->vbuf, u_subresource(0,0),
+   pipe->transfer_inline_write(pipe, ctx->vbuf, 0,
                                PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
                                &box, ctx->vertices, sizeof(ctx->vertices), 0);
 
@@ -709,21 +709,22 @@
 
 void util_blitter_copy_region(struct blitter_context *blitter,
                               struct pipe_resource *dst,
-                              struct pipe_subresource subdst,
+                              unsigned dstlevel,
                               unsigned dstx, unsigned dsty, unsigned dstz,
                               struct pipe_resource *src,
-                              struct pipe_subresource subsrc,
-                              unsigned srcx, unsigned srcy, unsigned srcz,
-                              unsigned width, unsigned height,
+                              unsigned srclevel,
+                              const struct pipe_box *srcbox,
                               boolean ignore_stencil)
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_screen *screen = pipe->screen;
-   struct pipe_surface *dstsurf;
+   struct pipe_surface *dstsurf, surf_templ;
    struct pipe_framebuffer_state fb_state;
    struct pipe_sampler_view viewTempl, *view;
    unsigned bind;
+   unsigned width = srcbox->width;
+   unsigned height = srcbox->height;
    boolean is_stencil, is_depth;
    boolean normalized;
 
@@ -734,12 +735,14 @@
 
    /* Sanity checks. */
    if (dst == src) {
-      assert(!is_overlap(srcx, srcx + width, srcy, srcy + height,
+      assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
                          dstx, dstx + width, dsty, dsty + height));
    } else {
       assert(dst->format == src->format);
    }
    assert(src->target < PIPE_MAX_TEXTURE_TYPES);
+   /* XXX should handle 3d regions */
+   assert(srcbox->depth == 1);
 
    /* Is this a ZS format? */
    is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
@@ -757,15 +760,18 @@
                                     dst->nr_samples, bind, 0) ||
        !screen->is_format_supported(screen, src->format, src->target,
                                     src->nr_samples, PIPE_BIND_SAMPLER_VIEW, 0)) {
-      util_resource_copy_region(pipe, dst, subdst, dstx, dsty, dstz,
-                                src, subsrc, srcx, srcy, srcz, width, height);
+      util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz,
+                                src, srclevel, srcbox);
       return;
    }
 
-   /* Get surfaces. */
-   dstsurf = screen->get_tex_surface(screen, dst,
-                                     subdst.face, subdst.level, dstz,
-                                     bind);
+   /* Get surface. */
+   memset(&surf_templ, 0, sizeof(surf_templ));
+   u_surface_default_template(&surf_templ, dst, bind);
+   surf_templ.u.tex.level = dstlevel;
+   surf_templ.u.tex.first_layer = dstz;
+   surf_templ.u.tex.last_layer = dstz;
+   dstsurf = pipe->create_surface(pipe, dst, &surf_templ);
 
    /* Check whether the states are properly saved. */
    blitter_check_saved_CSOs(ctx);
@@ -807,7 +813,7 @@
    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
    pipe->bind_vs_state(pipe, ctx->vs);
    pipe->bind_fragment_sampler_states(pipe, 1,
-                                      blitter_get_sampler_state(ctx, subsrc.level, normalized));
+                                      blitter_get_sampler_state(ctx, srclevel, normalized));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
    pipe->set_fragment_sampler_views(pipe, 1, &view);
    pipe->set_framebuffer_state(pipe, &fb_state);
@@ -822,8 +828,8 @@
          {
             /* Set texture coordinates. */
             float coord[4];
-            get_texcoords(src, subsrc, srcx, srcy,
-                                     srcx+width, srcy+height, normalized, coord);
+            get_texcoords(src, srclevel, srcbox->x, srcbox->y,
+                          srcbox->x+width, srcbox->y+height, normalized, coord);
 
             /* Draw. */
             blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
@@ -836,11 +842,13 @@
       case PIPE_TEXTURE_CUBE:
          /* Set texture coordinates. */
          if (src->target == PIPE_TEXTURE_3D)
-            blitter_set_texcoords_3d(ctx, src, subsrc, srcz,
-                                     srcx, srcy, srcx+width, srcy+height);
+            blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z,
+                                     srcbox->x, srcbox->y,
+                                     srcbox->x + width, srcbox->y + height);
          else
-            blitter_set_texcoords_cube(ctx, src, subsrc,
-                                       srcx, srcy, srcx+width, srcy+height);
+            blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z,
+                                       srcbox->x, srcbox->y,
+                                       srcbox->x + width, srcbox->y + height);
 
          /* Draw. */
          blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index f9f96f2..c5660cf 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -164,12 +164,11 @@
  */
 void util_blitter_copy_region(struct blitter_context *blitter,
                               struct pipe_resource *dst,
-                              struct pipe_subresource subdst,
+                              unsigned dstlevel,
                               unsigned dstx, unsigned dsty, unsigned dstz,
                               struct pipe_resource *src,
-                              struct pipe_subresource subsrc,
-                              unsigned srcx, unsigned srcy, unsigned srcz,
-                              unsigned width, unsigned height,
+                              unsigned srclevel,
+                              const struct pipe_box *srcbox,
                               boolean ignore_stencil);
 
 /**
diff --git a/src/gallium/auxiliary/util/u_box.h b/src/gallium/auxiliary/util/u_box.h
index e9c7174..0b28d0f 100644
--- a/src/gallium/auxiliary/util/u_box.h
+++ b/src/gallium/auxiliary/util/u_box.h
@@ -60,7 +60,6 @@
    box->depth = 1;
 }
 
-
 static INLINE
 void u_box_3d( unsigned x,
 	       unsigned y,
@@ -78,15 +77,4 @@
    box->depth = d;
 }
 
-
-static INLINE
-struct pipe_subresource u_subresource( unsigned face,
-				       unsigned level )
-{
-   struct pipe_subresource subresource;
-   subresource.face = face;
-   subresource.level = level;
-   return subresource;
-}
-
 #endif
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
index 504e6d2..2ad2f95 100644
--- a/src/gallium/auxiliary/util/u_debug.c
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -40,7 +40,8 @@
 #include "util/u_string.h" 
 #include "util/u_math.h" 
 #include "util/u_tile.h" 
-#include "util/u_prim.h" 
+#include "util/u_prim.h"
+#include "util/u_surface.h"
 
 #include <limits.h> /* CHAR_BIT */
 
@@ -453,9 +454,10 @@
 #endif
 }
 
+/* FIXME: dump resources, not surfaces... */
 void debug_dump_surface(struct pipe_context *pipe,
-			const char *prefix,
-                        struct pipe_surface *surface)     
+                        const char *prefix,
+                        struct pipe_surface *surface)
 {
    struct pipe_resource *texture;
    struct pipe_transfer *transfer;
@@ -472,23 +474,23 @@
     */
    texture = surface->texture;
 
-   transfer = pipe_get_transfer(pipe, texture, surface->face,
-				     surface->level, surface->zslice,
-				     PIPE_TRANSFER_READ, 0, 0, surface->width,
-				     surface->height);
-   
+   transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level,
+                                surface->u.tex.first_layer,
+                                PIPE_TRANSFER_READ,
+                                0, 0, surface->width, surface->height);
+
    data = pipe->transfer_map(pipe, transfer);
    if(!data)
       goto error;
-   
-   debug_dump_image(prefix, 
+
+   debug_dump_image(prefix,
                     texture->format,
-                    util_format_get_blocksize(texture->format), 
+                    util_format_get_blocksize(texture->format),
                     util_format_get_nblocksx(texture->format, surface->width),
                     util_format_get_nblocksy(texture->format, surface->height),
                     transfer->stride,
                     data);
-   
+
    pipe->transfer_unmap(pipe, transfer);
 error:
    pipe->transfer_destroy(pipe, transfer);
@@ -499,20 +501,18 @@
                         const char *prefix,
                         struct pipe_resource *texture)
 {
-   struct pipe_surface *surface;
-   struct pipe_screen *screen;
+   struct pipe_surface *surface, surf_tmpl;
 
    if (!texture)
       return;
 
-   screen = texture->screen;
-
-   /* XXX for now, just dump image for face=0, level=0 */
-   surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
-                                     PIPE_BIND_SAMPLER_VIEW);
+   /* XXX for now, just dump image for layer=0, level=0 */
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, texture, 0 /* no bind flag - not a surface */);
+   surface = pipe->create_surface(pipe, texture, &surf_tmpl);
    if (surface) {
       debug_dump_surface(pipe, prefix, surface);
-      screen->tex_surface_destroy(surface);
+      pipe->surface_destroy(pipe, surface);
    }
 }
 
@@ -550,17 +550,16 @@
 
 void
 debug_dump_surface_bmp(struct pipe_context *pipe,
-		       const char *filename,
+                       const char *filename,
                        struct pipe_surface *surface)
 {
 #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
    struct pipe_transfer *transfer;
    struct pipe_resource *texture = surface->texture;
 
-   transfer = pipe_get_transfer(pipe, texture, surface->face,
-				surface->level, surface->zslice,
-				PIPE_TRANSFER_READ, 0, 0, surface->width,
-				surface->height);
+   transfer = pipe_get_transfer(pipe, texture, surface->u.tex.level,
+                                surface->u.tex.first_layer, PIPE_TRANSFER_READ,
+                                0, 0, surface->width, surface->height);
 
    debug_dump_transfer_bmp(pipe, filename, transfer);
 
diff --git a/src/gallium/auxiliary/util/u_debug_describe.c b/src/gallium/auxiliary/util/u_debug_describe.c
index 1c90ff3..7ed8ee6 100644
--- a/src/gallium/auxiliary/util/u_debug_describe.c
+++ b/src/gallium/auxiliary/util/u_debug_describe.c
@@ -69,7 +69,7 @@
 {
    char res[128];
    debug_describe_resource(res, ptr->texture);
-   util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->face, ptr->level, ptr->zslice);
+   util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->u.tex.level, ptr->u.tex.first_layer, ptr->u.tex.last_layer);
 }
 
 void
diff --git a/src/gallium/auxiliary/util/u_dirty_surfaces.h b/src/gallium/auxiliary/util/u_dirty_surfaces.h
index fd1bbe5..f3618d9 100644
--- a/src/gallium/auxiliary/util/u_dirty_surfaces.h
+++ b/src/gallium/auxiliary/util/u_dirty_surfaces.h
@@ -77,7 +77,7 @@
       struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list);
       next = p->next;
 
-      if(ds->base.level >= first && ds->base.level <= last)
+      if(ds->base.u.tex.level >= first && ds->base.u.tex.level <= last)
 	 flush(pipe, &ds->base);
    }
 }
@@ -86,7 +86,8 @@
 util_dirty_surfaces_use_for_sampling_with(struct pipe_context *pipe, struct util_dirty_surfaces *dss, struct pipe_sampler_view *psv, struct pipe_sampler_state *pss, util_dirty_surface_flush_t flush)
 {
    if(!LIST_IS_EMPTY(&dss->dirty_list))
-      util_dirty_surfaces_use_levels_for_sampling(pipe, dss, (unsigned)pss->min_lod + psv->first_level, MIN2((unsigned)ceilf(pss->max_lod) + psv->first_level, psv->last_level), flush);
+      util_dirty_surfaces_use_levels_for_sampling(pipe, dss, (unsigned)pss->min_lod + psv->u.tex.first_level,
+						  MIN2((unsigned)ceilf(pss->max_lod) + psv->u.tex.first_level, psv->u.tex.last_level), flush);
 }
 
 static INLINE void
diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c
index cda5b8b..b471d59 100644
--- a/src/gallium/auxiliary/util/u_dump_state.c
+++ b/src/gallium/auxiliary/util/u_dump_state.c
@@ -279,6 +279,10 @@
    util_dump_uint(stream, templat->depth0);
    util_dump_member_end(stream);
 
+   util_dump_member_begin(stream, "array_size");
+   util_dump_uint(stream, templat->array_size);
+   util_dump_member_end(stream);
+
    util_dump_member(stream, uint, templat, last_level);
    util_dump_member(stream, uint, templat, usage);
    util_dump_member(stream, uint, templat, bind);
@@ -633,14 +637,12 @@
    util_dump_member(stream, uint, state, width);
    util_dump_member(stream, uint, state, height);
 
-   util_dump_member(stream, uint, state, layout);
-   util_dump_member(stream, uint, state, offset);
    util_dump_member(stream, uint, state, usage);
 
    util_dump_member(stream, ptr, state, texture);
-   util_dump_member(stream, uint, state, face);
-   util_dump_member(stream, uint, state, level);
-   util_dump_member(stream, uint, state, zslice);
+   util_dump_member(stream, uint, state, u.tex.level);
+   util_dump_member(stream, uint, state, u.tex.first_layer);
+   util_dump_member(stream, uint, state, u.tex.last_layer);
 
    util_dump_struct_end(stream);
 }
@@ -660,7 +662,7 @@
    /*util_dump_member(stream, uint, state, box);*/
 
    util_dump_member(stream, uint, state, stride);
-   util_dump_member(stream, uint, state, slice_stride);
+   util_dump_member(stream, uint, state, layer_stride);
 
    /*util_dump_member(stream, ptr, state, data);*/
 
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index 6a931a9..d4716bf 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -48,6 +48,8 @@
 #include "util/u_simple_shaders.h"
 #include "util/u_math.h"
 #include "util/u_texture.h"
+#include "util/u_half.h"
+#include "util/u_surface.h"
 
 #include "cso_cache/cso_context.h"
 
@@ -65,7 +67,7 @@
    struct pipe_vertex_element velem[2];
 
    void *vs;
-   void *fs2d, *fsCube;
+   void *fs1d, *fs2d, *fs3d, *fsCube;
 
    struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
@@ -89,24 +91,7 @@
 };
 
 
-typedef ushort half_float;
-
-
-static half_float
-float_to_half(float f)
-{
-   /* XXX fix this */
-   return 0;
-}
-
-static float
-half_to_float(half_float h)
-{
-   /* XXX fix this */
-   return 0.0f;
-}
-
-
+typedef uint16_t half_float;
 
 
 /**
@@ -145,7 +130,7 @@
                                 rowC[j][e], rowC[k][e], \
                                 rowD[j][e], rowD[k][e]); \
    } while(0)
-   
+
 #define FILTER_F_3D(e) \
    do { \
       dst[i][e] = (rowA[j][e] + rowA[k][e] \
@@ -156,15 +141,15 @@
 
 #define FILTER_HF_3D(e) \
    do { \
-      const float aj = half_to_float(rowA[j][e]); \
-      const float ak = half_to_float(rowA[k][e]); \
-      const float bj = half_to_float(rowB[j][e]); \
-      const float bk = half_to_float(rowB[k][e]); \
-      const float cj = half_to_float(rowC[j][e]); \
-      const float ck = half_to_float(rowC[k][e]); \
-      const float dj = half_to_float(rowD[j][e]); \
-      const float dk = half_to_float(rowD[k][e]); \
-      dst[i][e] = float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
+      const float aj = util_half_to_float(rowA[j][e]); \
+      const float ak = util_half_to_float(rowA[k][e]); \
+      const float bj = util_half_to_float(rowB[j][e]); \
+      const float bk = util_half_to_float(rowB[k][e]); \
+      const float cj = util_half_to_float(rowC[j][e]); \
+      const float ck = util_half_to_float(rowC[k][e]); \
+      const float dj = util_half_to_float(rowD[j][e]); \
+      const float dk = util_half_to_float(rowD[k][e]); \
+      dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
                                       * 0.125F); \
    } while(0)
 /*@}*/
@@ -343,8 +328,7 @@
       }
    }
 
-#if 0
-   else if (datatype == HALF_DTYPE_FLOAT && comps == 4) {
+   else if (datatype == DTYPE_HALF_FLOAT && comps == 4) {
       uint i, j, k, comp;
       const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
       const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
@@ -353,11 +337,11 @@
            i++, j += colStride, k += colStride) {
          for (comp = 0; comp < 4; comp++) {
             float aj, ak, bj, bk;
-            aj = half_to_float(rowA[j][comp]);
-            ak = half_to_float(rowA[k][comp]);
-            bj = half_to_float(rowB[j][comp]);
-            bk = half_to_float(rowB[k][comp]);
-            dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+            aj = util_half_to_float(rowA[j][comp]);
+            ak = util_half_to_float(rowA[k][comp]);
+            bj = util_half_to_float(rowB[j][comp]);
+            bk = util_half_to_float(rowB[k][comp]);
+            dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
          }
       }
    }
@@ -370,11 +354,11 @@
            i++, j += colStride, k += colStride) {
          for (comp = 0; comp < 3; comp++) {
             float aj, ak, bj, bk;
-            aj = half_to_float(rowA[j][comp]);
-            ak = half_to_float(rowA[k][comp]);
-            bj = half_to_float(rowB[j][comp]);
-            bk = half_to_float(rowB[k][comp]);
-            dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+            aj = util_half_to_float(rowA[j][comp]);
+            ak = util_half_to_float(rowA[k][comp]);
+            bj = util_half_to_float(rowB[j][comp]);
+            bk = util_half_to_float(rowB[k][comp]);
+            dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
          }
       }
    }
@@ -387,11 +371,11 @@
            i++, j += colStride, k += colStride) {
          for (comp = 0; comp < 2; comp++) {
             float aj, ak, bj, bk;
-            aj = half_to_float(rowA[j][comp]);
-            ak = half_to_float(rowA[k][comp]);
-            bj = half_to_float(rowB[j][comp]);
-            bk = half_to_float(rowB[k][comp]);
-            dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+            aj = util_half_to_float(rowA[j][comp]);
+            ak = util_half_to_float(rowA[k][comp]);
+            bj = util_half_to_float(rowB[j][comp]);
+            bk = util_half_to_float(rowB[k][comp]);
+            dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
          }
       }
    }
@@ -403,14 +387,13 @@
       for (i = j = 0, k = k0; i < (uint) dstWidth;
            i++, j += colStride, k += colStride) {
          float aj, ak, bj, bk;
-         aj = half_to_float(rowA[j]);
-         ak = half_to_float(rowA[k]);
-         bj = half_to_float(rowB[j]);
-         bk = half_to_float(rowB[k]);
-         dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
+         aj = util_half_to_float(rowA[j]);
+         ak = util_half_to_float(rowA[k]);
+         bj = util_half_to_float(rowB[j]);
+         bk = util_half_to_float(rowB[k]);
+         dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
       }
    }
-#endif
 
    else if (datatype == DTYPE_UINT && comps == 1) {
       uint i, j, k;
@@ -1036,32 +1019,34 @@
 static void
 reduce_3d(enum pipe_format pformat,
           int srcWidth, int srcHeight, int srcDepth,
-          int srcRowStride, const ubyte *srcPtr,
+          int srcRowStride, int srcImageStride, const ubyte *srcPtr,
           int dstWidth, int dstHeight, int dstDepth,
-          int dstRowStride, ubyte *dstPtr)
+          int dstRowStride, int dstImageStride, ubyte *dstPtr)
 {
    const int bpt = util_format_get_blocksize(pformat);
-   const int border = 0;
    int img, row;
-   int bytesPerSrcImage, bytesPerDstImage;
-   int bytesPerSrcRow, bytesPerDstRow;
    int srcImageOffset, srcRowOffset;
    enum dtype datatype;
    uint comps;
 
    format_to_type_comps(pformat, &datatype, &comps);
 
-   bytesPerSrcImage = srcWidth * srcHeight * bpt;
-   bytesPerDstImage = dstWidth * dstHeight * bpt;
+   /* XXX I think we should rather assert those strides */
+   if (!srcImageStride)
+      srcImageStride = srcWidth * srcHeight * bpt;
+   if (!dstImageStride)
+      dstImageStride = dstWidth * dstHeight * bpt;
 
-   bytesPerSrcRow = srcWidth * bpt;
-   bytesPerDstRow = dstWidth * bpt;
+   if (!srcRowStride)
+      srcRowStride = srcWidth * bpt;
+   if (!dstRowStride)
+      dstRowStride = dstWidth * bpt;
 
    /* Offset between adjacent src images to be averaged together */
-   srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
+   srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride;
 
    /* Offset between adjacent src rows to be averaged together */
-   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
+   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride;
 
    /*
     * Need to average together up to 8 src pixels for each dest pixel.
@@ -1077,16 +1062,14 @@
    */
 
    for (img = 0; img < dstDepth; img++) {
-      /* first source image pointer, skipping border */
+      /* first source image pointer */
       const ubyte *imgSrcA = srcPtr
-         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
-         + img * (bytesPerSrcImage + srcImageOffset);
-      /* second source image pointer, skipping border */
+         + img * (srcImageStride + srcImageOffset);
+      /* second source image pointer */
       const ubyte *imgSrcB = imgSrcA + srcImageOffset;
-      /* address of the dest image, skipping border */
+      /* address of the dest image */
       ubyte *imgDst = dstPtr
-         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
-         + img * bytesPerDstImage;
+         + img * dstImageStride;
 
       /* setup the four source row pointers and the dest row pointer */
       const ubyte *srcImgARowA = imgSrcA;
@@ -1102,11 +1085,11 @@
                    dstWidth, dstImgRow);
 
          /* advance to next rows */
-         srcImgARowA += bytesPerSrcRow + srcRowOffset;
-         srcImgARowB += bytesPerSrcRow + srcRowOffset;
-         srcImgBRowA += bytesPerSrcRow + srcRowOffset;
-         srcImgBRowB += bytesPerSrcRow + srcRowOffset;
-         dstImgRow += bytesPerDstRow;
+         srcImgARowA += srcRowStride + srcRowOffset;
+         srcImgARowB += srcRowStride + srcRowOffset;
+         srcImgBRowA += srcRowStride + srcRowOffset;
+         srcImgBRowB += srcRowStride + srcRowOffset;
+         dstImgRow += dstImageStride;
       }
    }
 }
@@ -1117,25 +1100,24 @@
 static void
 make_1d_mipmap(struct gen_mipmap_state *ctx,
                struct pipe_resource *pt,
-               uint face, uint baseLevel, uint lastLevel)
+               uint layer, uint baseLevel, uint lastLevel)
 {
    struct pipe_context *pipe = ctx->pipe;
-   const uint zslice = 0;
    uint dstLevel;
 
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
       struct pipe_transfer *srcTrans, *dstTrans;
       void *srcMap, *dstMap;
-      
-      srcTrans = pipe_get_transfer(pipe, pt, face, srcLevel, zslice,
-                                          PIPE_TRANSFER_READ, 0, 0,
-                                          u_minify(pt->width0, srcLevel),
-                                          u_minify(pt->height0, srcLevel));
-      dstTrans = pipe_get_transfer(pipe, pt, face, dstLevel, zslice,
-                                          PIPE_TRANSFER_WRITE, 0, 0,
-                                          u_minify(pt->width0, dstLevel),
-                                          u_minify(pt->height0, dstLevel));
+
+      srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer,
+                                   PIPE_TRANSFER_READ, 0, 0,
+                                   u_minify(pt->width0, srcLevel),
+                                   u_minify(pt->height0, srcLevel));
+      dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer,
+                                   PIPE_TRANSFER_WRITE, 0, 0,
+                                   u_minify(pt->width0, dstLevel),
+                                   u_minify(pt->height0, dstLevel));
 
       srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
       dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
@@ -1156,12 +1138,11 @@
 static void
 make_2d_mipmap(struct gen_mipmap_state *ctx,
                struct pipe_resource *pt,
-               uint face, uint baseLevel, uint lastLevel)
+               uint layer, uint baseLevel, uint lastLevel)
 {
    struct pipe_context *pipe = ctx->pipe;
-   const uint zslice = 0;
    uint dstLevel;
-   
+
    assert(util_format_get_blockwidth(pt->format) == 1);
    assert(util_format_get_blockheight(pt->format) == 1);
 
@@ -1169,15 +1150,15 @@
       const uint srcLevel = dstLevel - 1;
       struct pipe_transfer *srcTrans, *dstTrans;
       ubyte *srcMap, *dstMap;
-      
-      srcTrans = pipe_get_transfer(pipe, pt, face, srcLevel, zslice,
-				   PIPE_TRANSFER_READ, 0, 0,
-				   u_minify(pt->width0, srcLevel),
-				   u_minify(pt->height0, srcLevel));
-      dstTrans = pipe_get_transfer(pipe, pt, face, dstLevel, zslice,
-				   PIPE_TRANSFER_WRITE, 0, 0,
-				   u_minify(pt->width0, dstLevel),
-				   u_minify(pt->height0, dstLevel));
+
+      srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer,
+                                   PIPE_TRANSFER_READ, 0, 0,
+                                   u_minify(pt->width0, srcLevel),
+                                   u_minify(pt->height0, srcLevel));
+      dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer,
+                                   PIPE_TRANSFER_WRITE, 0, 0,
+                                   u_minify(pt->width0, dstLevel),
+                                   u_minify(pt->height0, dstLevel));
 
       srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
       dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
@@ -1197,41 +1178,49 @@
 }
 
 
+/* XXX looks a bit more like it could work now but need to test */
 static void
 make_3d_mipmap(struct gen_mipmap_state *ctx,
                struct pipe_resource *pt,
                uint face, uint baseLevel, uint lastLevel)
 {
-#if 0
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   uint dstLevel, zslice = 0;
+   uint dstLevel;
+   struct pipe_box src_box, dst_box;
 
    assert(util_format_get_blockwidth(pt->format) == 1);
    assert(util_format_get_blockheight(pt->format) == 1);
 
+   src_box.x = src_box.y = src_box.z = 0;
+   dst_box.x = dst_box.y = dst_box.z = 0;
+
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
       struct pipe_transfer *srcTrans, *dstTrans;
       ubyte *srcMap, *dstMap;
-      
-      srcTrans = pipe->get_transfer(pipe, pt, face, srcLevel, zslice,
-                                          PIPE_TRANSFER_READ, 0, 0,
-                                          u_minify(pt->width0, srcLevel),
-                                          u_minify(pt->height0, srcLevel));
-      dstTrans = pipe->get_transfer(pipe, pt, face, dstLevel, zslice,
-                                          PIPE_TRANSFER_WRITE, 0, 0,
-                                          u_minify(pt->width0, dstLevel),
-                                          u_minify(pt->height0, dstLevel));
+      struct pipe_box src_box, dst_box;
+      src_box.width = u_minify(pt->width0, srcLevel);
+      src_box.height = u_minify(pt->height0, srcLevel);
+      src_box.depth = u_minify(pt->depth0, srcLevel);
+      dst_box.width = u_minify(pt->width0, dstLevel);
+      dst_box.height = u_minify(pt->height0, dstLevel);
+      dst_box.depth = u_minify(pt->depth0, dstLevel);
+
+      srcTrans = pipe->get_transfer(pipe, pt, srcLevel,
+                                    PIPE_TRANSFER_READ,
+                                    &src_box);
+      dstTrans = pipe->get_transfer(pipe, pt, dstLevel,
+                                    PIPE_TRANSFER_WRITE,
+                                    &dst_box);
 
       srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
       dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
 
       reduce_3d(pt->format,
-                srcTrans->width, srcTrans->height,
-                srcTrans->stride, srcMap,
-                dstTrans->width, dstTrans->height,
-                dstTrans->stride, dstMap);
+                srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth,
+                srcTrans->stride, srcTrans->layer_stride, srcMap,
+                dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth,
+                dstTrans->stride, dstTrans->layer_stride, dstMap);
 
       pipe->transfer_unmap(pipe, srcTrans);
       pipe->transfer_unmap(pipe, dstTrans);
@@ -1239,28 +1228,25 @@
       pipe->transfer_destroy(pipe, srcTrans);
       pipe->transfer_destroy(pipe, dstTrans);
    }
-#else
-   (void) reduce_3d;
-#endif
 }
 
 
 static void
 fallback_gen_mipmap(struct gen_mipmap_state *ctx,
                     struct pipe_resource *pt,
-                    uint face, uint baseLevel, uint lastLevel)
+                    uint layer, uint baseLevel, uint lastLevel)
 {
    switch (pt->target) {
    case PIPE_TEXTURE_1D:
-      make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+      make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
       break;
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
-      make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+      make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
       break;
    case PIPE_TEXTURE_3D:
-      make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+      make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
       break;
    default:
       assert(0);
@@ -1328,8 +1314,12 @@
    }
 
    /* fragment shader */
+   ctx->fs1d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_1D,
+                                             TGSI_INTERPOLATE_LINEAR);
    ctx->fs2d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
                                              TGSI_INTERPOLATE_LINEAR);
+   ctx->fs3d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_3D,
+                                               TGSI_INTERPOLATE_LINEAR);
    ctx->fsCube = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE,
                                                TGSI_INTERPOLATE_LINEAR);
 
@@ -1371,7 +1361,7 @@
 static unsigned
 set_vertex_data(struct gen_mipmap_state *ctx,
                 enum pipe_texture_target tex_target,
-                uint face)
+                uint layer, float r)
 {
    unsigned offset;
 
@@ -1397,26 +1387,26 @@
          {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
       };
 
-      util_map_texcoords2d_onto_cubemap(face, &st[0][0], 2,
+      util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2,
                                         &ctx->vertices[0][1][0], 8);
    }
    else {
-      /* 1D/2D */
+      /* 1D/2D/3D */
       ctx->vertices[0][1][0] = 0.0f; /*s*/
       ctx->vertices[0][1][1] = 0.0f; /*t*/
-      ctx->vertices[0][1][2] = 0.0f; /*r*/
+      ctx->vertices[0][1][2] = r;    /*r*/
 
       ctx->vertices[1][1][0] = 1.0f;
       ctx->vertices[1][1][1] = 0.0f;
-      ctx->vertices[1][1][2] = 0.0f;
+      ctx->vertices[1][1][2] = r;
 
       ctx->vertices[2][1][0] = 1.0f;
       ctx->vertices[2][1][1] = 1.0f;
-      ctx->vertices[2][1][2] = 0.0f;
+      ctx->vertices[2][1][2] = r;
 
       ctx->vertices[3][1][0] = 0.0f;
       ctx->vertices[3][1][1] = 1.0f;
-      ctx->vertices[3][1][2] = 0.0f;
+      ctx->vertices[3][1][2] = r;
    }
 
    offset = get_next_slot( ctx );
@@ -1478,9 +1468,8 @@
    struct pipe_screen *screen = pipe->screen;
    struct pipe_framebuffer_state fb;
    struct pipe_resource *pt = psv->texture;
-   void *fs = (pt->target == PIPE_TEXTURE_CUBE) ? ctx->fsCube : ctx->fs2d;
+   void *fs;
    uint dstLevel;
-   uint zslice = 0;
    uint offset;
 
    /* The texture object should have room for the levels which we're
@@ -1494,8 +1483,28 @@
    assert(filter == PIPE_TEX_FILTER_LINEAR ||
           filter == PIPE_TEX_FILTER_NEAREST);
 
+   switch (pt->target) {
+   case PIPE_TEXTURE_1D:
+      fs = ctx->fs1d;
+      break;
+   case PIPE_TEXTURE_2D:
+      fs = ctx->fs2d;
+      break;
+   case PIPE_TEXTURE_3D:
+      fs = ctx->fs3d;
+      break;
+   case PIPE_TEXTURE_CUBE:
+      fs = ctx->fsCube;
+      break;
+   case PIPE_TEXTURE_1D_ARRAY:
+   case PIPE_TEXTURE_2D_ARRAY:
+   default:
+      assert(0);
+      fs = ctx->fs2d;
+   }
+
    /* check if we can render in the texture's format */
-   if (!screen->is_format_supported(screen, psv->format, PIPE_TEXTURE_2D,
+   if (!screen->is_format_supported(screen, psv->format, pt->target,
                                     pt->nr_samples, PIPE_BIND_RENDER_TARGET, 0)) {
       fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
       return;
@@ -1539,60 +1548,84 @@
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
       struct pipe_viewport_state vp;
+      unsigned nr_layers, layer, i;
+      float rcoord = 0.0f;
 
-      struct pipe_surface *surf = 
-         screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
-                                 PIPE_BIND_RENDER_TARGET);
+      if (pt->target == PIPE_TEXTURE_3D)
+         nr_layers = u_minify(pt->depth0, dstLevel);
+      else nr_layers = 1;
 
-      /*
-       * Setup framebuffer / dest surface
-       */
-      fb.cbufs[0] = surf;
-      fb.width = u_minify(pt->width0, dstLevel);
-      fb.height = u_minify(pt->height0, dstLevel);
-      cso_set_framebuffer(ctx->cso, &fb);
+      for (i = 0; i < nr_layers; i++) {
+         struct pipe_surface *surf, surf_templ;
+         if (pt->target == PIPE_TEXTURE_3D) {
+            /* in theory with geom shaders and driver with full layer support
+               could do that in one go. */
+            layer = i;
+            offset = 1.0f / (float)(nr_layers * 2);
+            /* XXX hmm really? */
+            rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
+         }
+         else
+            layer = face;
 
-      /* viewport */
-      vp.scale[0] = 0.5f * fb.width;
-      vp.scale[1] = 0.5f * fb.height;
-      vp.scale[2] = 1.0f;
-      vp.scale[3] = 1.0f;
-      vp.translate[0] = 0.5f * fb.width;
-      vp.translate[1] = 0.5f * fb.height;
-      vp.translate[2] = 0.0f;
-      vp.translate[3] = 0.0f;
-      cso_set_viewport(ctx->cso, &vp);
+         memset(&surf_templ, 0, sizeof(surf_templ));
+         u_surface_default_template(&surf_templ, pt, PIPE_BIND_RENDER_TARGET);
+         surf_templ.u.tex.level = dstLevel;
+         surf_templ.u.tex.first_layer = layer;
+         surf_templ.u.tex.last_layer = layer;
+         surf = pipe->create_surface(pipe, pt, &surf_templ);
 
-      /*
-       * Setup sampler state
-       * Note: we should only have to set the min/max LOD clamps to ensure
-       * we grab texels from the right mipmap level.  But some hardware
-       * has trouble with min clamping so we also set the lod_bias to
-       * try to work around that.
-       */
-      ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
-      ctx->sampler.lod_bias = (float) srcLevel;
-      cso_single_sampler(ctx->cso, 0, &ctx->sampler);
-      cso_single_sampler_done(ctx->cso);
+         /*
+          * Setup framebuffer / dest surface
+          */
+         fb.cbufs[0] = surf;
+         fb.width = u_minify(pt->width0, dstLevel);
+         fb.height = u_minify(pt->height0, dstLevel);
+         cso_set_framebuffer(ctx->cso, &fb);
 
-      cso_set_fragment_sampler_views(ctx->cso, 1, &psv);
+         /* viewport */
+         vp.scale[0] = 0.5f * fb.width;
+         vp.scale[1] = 0.5f * fb.height;
+         vp.scale[2] = 1.0f;
+         vp.scale[3] = 1.0f;
+         vp.translate[0] = 0.5f * fb.width;
+         vp.translate[1] = 0.5f * fb.height;
+         vp.translate[2] = 0.0f;
+         vp.translate[3] = 0.0f;
+         cso_set_viewport(ctx->cso, &vp);
 
-      /* quad coords in clip coords */
-      offset = set_vertex_data(ctx,
-                               pt->target,
-                               face);
+         /*
+          * Setup sampler state
+          * Note: we should only have to set the min/max LOD clamps to ensure
+          * we grab texels from the right mipmap level.  But some hardware
+          * has trouble with min clamping so we also set the lod_bias to
+          * try to work around that.
+          */
+         ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
+         ctx->sampler.lod_bias = (float) srcLevel;
+         cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+         cso_single_sampler_done(ctx->cso);
 
-      util_draw_vertex_buffer(ctx->pipe, 
-                              ctx->vbuf,
-                              offset,
-                              PIPE_PRIM_TRIANGLE_FAN,
-                              4,  /* verts */
-                              2); /* attribs/vert */
+         cso_set_fragment_sampler_views(ctx->cso, 1, &psv);
 
-      pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+         /* quad coords in clip coords */
+         offset = set_vertex_data(ctx,
+                                  pt->target,
+                                  face,
+                                  rcoord);
 
-      /* need to signal that the texture has changed _after_ rendering to it */
-      pipe_surface_reference( &surf, NULL );
+         util_draw_vertex_buffer(ctx->pipe, 
+                                 ctx->vbuf,
+                                 offset,
+                                 PIPE_PRIM_TRIANGLE_FAN,
+                                 4,  /* verts */
+                                 2); /* attribs/vert */
+
+         pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+         /* need to signal that the texture has changed _after_ rendering to it */
+         pipe_surface_reference( &surf, NULL );
+      }
    }
 
    /* restore state we changed */
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
index a7502b9..a10b6a4 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.h
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -60,7 +60,7 @@
 extern void
 util_gen_mipmap(struct gen_mipmap_state *ctx,
                 struct pipe_sampler_view *psv,
-                uint face, uint baseLevel, uint lastLevel, uint filter);
+                uint layer, uint baseLevel, uint lastLevel, uint filter);
 
 
 #ifdef __cplusplus
diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h
index 6ed3956..d5bc114 100644
--- a/src/gallium/auxiliary/util/u_inlines.h
+++ b/src/gallium/auxiliary/util/u_inlines.h
@@ -109,7 +109,7 @@
 
    if (pipe_reference_described(&(*ptr)->reference, &surf->reference, 
                                 (debug_reference_descriptor)debug_describe_surface))
-      old_surf->texture->screen->tex_surface_destroy(old_surf);
+      old_surf->context->surface_destroy(old_surf->context, old_surf);
    *ptr = surf;
 }
 
@@ -137,25 +137,24 @@
 
 static INLINE void
 pipe_surface_reset(struct pipe_surface* ps, struct pipe_resource *pt,
-		unsigned face, unsigned level, unsigned zslice, unsigned flags)
+                   unsigned level, unsigned layer, unsigned flags)
 {
    pipe_resource_reference(&ps->texture, pt);
    ps->format = pt->format;
    ps->width = u_minify(pt->width0, level);
    ps->height = u_minify(pt->height0, level);
    ps->usage = flags;
-   ps->face = face;
-   ps->level = level;
-   ps->zslice = zslice;
+   ps->u.tex.level = level;
+   ps->u.tex.first_layer = ps->u.tex.last_layer = layer;
 }
 
 static INLINE void
 pipe_surface_init(struct pipe_surface* ps, struct pipe_resource *pt,
-                unsigned face, unsigned level, unsigned zslice, unsigned flags)
+                  unsigned level, unsigned layer, unsigned flags)
 {
    ps->texture = 0;
    pipe_reference_init(&ps->reference, 1);
-   pipe_surface_reset(ps, pt, face, level, zslice, flags);
+   pipe_surface_reset(ps, pt, level, layer, flags);
 }
 
 /*
@@ -177,6 +176,7 @@
    buffer.width0 = size;
    buffer.height0 = 1;
    buffer.depth0 = 1;
+   buffer.array_size = 1;
    return screen->resource_create(screen, &buffer);
 }
 
@@ -202,15 +202,15 @@
    assert(offset < buffer->width0);
    assert(offset + length <= buffer->width0);
    assert(length);
-   
+
    u_box_1d(offset, length, &box);
 
    *transfer = pipe->get_transfer( pipe,
-				   buffer,
-				   u_subresource(0, 0),
-				   usage,
-				   &box);
-   
+                                   buffer,
+                                   0,
+                                   usage,
+                                   &box);
+
    if (*transfer == NULL)
       return NULL;
 
@@ -231,7 +231,7 @@
 pipe_buffer_map(struct pipe_context *pipe,
                 struct pipe_resource *buffer,
                 unsigned usage,
-		struct pipe_transfer **transfer)
+                struct pipe_transfer **transfer)
 {
    return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, usage, transfer);
 }
@@ -240,7 +240,7 @@
 static INLINE void
 pipe_buffer_unmap(struct pipe_context *pipe,
                   struct pipe_resource *buf,
-		  struct pipe_transfer *transfer)
+                  struct pipe_transfer *transfer)
 {
    if (transfer) {
       pipe->transfer_unmap(pipe, transfer);
@@ -250,7 +250,7 @@
 
 static INLINE void
 pipe_buffer_flush_mapped_range(struct pipe_context *pipe,
-			       struct pipe_transfer *transfer,
+                               struct pipe_transfer *transfer,
                                unsigned offset,
                                unsigned length)
 {
@@ -266,7 +266,7 @@
     * mapped range.
     */
    transfer_offset = offset - transfer->box.x;
-   
+
    u_box_1d(transfer_offset, length, &box);
 
    pipe->transfer_flush_region(pipe, transfer, &box);
@@ -276,7 +276,7 @@
 pipe_buffer_write(struct pipe_context *pipe,
                   struct pipe_resource *buf,
                   unsigned offset,
-		  unsigned size,
+                  unsigned size,
                   const void *data)
 {
    struct pipe_box box;
@@ -284,13 +284,13 @@
    u_box_1d(offset, size, &box);
 
    pipe->transfer_inline_write( pipe,
-				buf,
-				u_subresource(0,0),
-				PIPE_TRANSFER_WRITE,
-				&box,
-				data,
-				size,
-				0);
+                                buf,
+                                0,
+                                PIPE_TRANSFER_WRITE,
+                                &box,
+                                data,
+                                size,
+                                0);
 }
 
 /**
@@ -309,21 +309,21 @@
 
    u_box_1d(offset, size, &box);
 
-   pipe->transfer_inline_write(pipe, 
-			       buf,
-			       u_subresource(0,0),
-			       (PIPE_TRANSFER_WRITE |
-				PIPE_TRANSFER_NOOVERWRITE),
-			       &box,
-			       data,
-			       0, 0);
+   pipe->transfer_inline_write(pipe,
+                               buf,
+                               0,
+                               (PIPE_TRANSFER_WRITE |
+                                PIPE_TRANSFER_NOOVERWRITE),
+                               &box,
+                               data,
+                               0, 0);
 }
 
 static INLINE void
 pipe_buffer_read(struct pipe_context *pipe,
                  struct pipe_resource *buf,
                  unsigned offset,
-		 unsigned size,
+                 unsigned size,
                  void *data)
 {
    struct pipe_transfer *src_transfer;
@@ -343,20 +343,19 @@
 
 static INLINE struct pipe_transfer *
 pipe_get_transfer( struct pipe_context *context,
-		       struct pipe_resource *resource,
-		       unsigned face, unsigned level,
-		       unsigned zslice,
-		       enum pipe_transfer_usage usage,
-		       unsigned x, unsigned y,
-		       unsigned w, unsigned h)
+                   struct pipe_resource *resource,
+                   unsigned level, unsigned layer,
+                   enum pipe_transfer_usage usage,
+                   unsigned x, unsigned y,
+                   unsigned w, unsigned h)
 {
    struct pipe_box box;
-   u_box_2d_zslice( x, y, zslice, w, h, &box );
+   u_box_2d_zslice( x, y, layer, w, h, &box );
    return context->get_transfer( context,
-				 resource,
-				 u_subresource(face, level),
-				 usage,
-				 &box );
+                                 resource,
+                                 level,
+                                 usage,
+                                 &box );
 }
 
 static INLINE void *
@@ -376,7 +375,7 @@
 
 static INLINE void
 pipe_transfer_destroy( struct pipe_context *context, 
-		       struct pipe_transfer *transfer )
+                       struct pipe_transfer *transfer )
 {
    context->transfer_destroy(context, transfer);
 }
diff --git a/src/gallium/auxiliary/util/u_resource.c b/src/gallium/auxiliary/util/u_resource.c
index 9e6474b..443c9f8 100644
--- a/src/gallium/auxiliary/util/u_resource.c
+++ b/src/gallium/auxiliary/util/u_resource.c
@@ -10,85 +10,85 @@
 }
 
 boolean u_resource_get_handle_vtbl(struct pipe_screen *screen,
-			  struct pipe_resource *resource,
-			  struct winsys_handle *handle)
+                                   struct pipe_resource *resource,
+                                   struct winsys_handle *handle)
 {
    struct u_resource *ur = u_resource(resource);
    return ur->vtbl->resource_get_handle(screen, resource, handle);
 }
 
 void u_resource_destroy_vtbl(struct pipe_screen *screen,
-		    struct pipe_resource *resource)
+                             struct pipe_resource *resource)
 {
    struct u_resource *ur = u_resource(resource);
    ur->vtbl->resource_destroy(screen, resource);
 }
 
 unsigned u_is_resource_referenced_vtbl( struct pipe_context *pipe,
-					struct pipe_resource *resource,
-					unsigned face, unsigned level)
+                                        struct pipe_resource *resource,
+                                        unsigned level, int layer)
 {
    struct u_resource *ur = u_resource(resource);
-   return ur->vtbl->is_resource_referenced(pipe, resource, face, level);
+   return ur->vtbl->is_resource_referenced(pipe, resource, level, layer);
 }
 
 struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context,
-					  struct pipe_resource *resource,
-					  struct pipe_subresource sr,
-					  enum pipe_transfer_usage usage,
-					  const struct pipe_box *box)
+                                          struct pipe_resource *resource,
+                                          unsigned level,
+                                          enum pipe_transfer_usage usage,
+                                          const struct pipe_box *box)
 {
    struct u_resource *ur = u_resource(resource);
-   return ur->vtbl->get_transfer(context, resource, sr, usage, box);
+   return ur->vtbl->get_transfer(context, resource, level, usage, box);
 }
 
 void u_transfer_destroy_vtbl(struct pipe_context *pipe,
-			     struct pipe_transfer *transfer)
+                             struct pipe_transfer *transfer)
 {
    struct u_resource *ur = u_resource(transfer->resource);
    ur->vtbl->transfer_destroy(pipe, transfer);
 }
 
 void *u_transfer_map_vtbl( struct pipe_context *pipe,
-			   struct pipe_transfer *transfer )
+                           struct pipe_transfer *transfer )
 {
    struct u_resource *ur = u_resource(transfer->resource);
    return ur->vtbl->transfer_map(pipe, transfer);
 }
 
 void u_transfer_flush_region_vtbl( struct pipe_context *pipe,
-				   struct pipe_transfer *transfer,
-				   const struct pipe_box *box)
+                                   struct pipe_transfer *transfer,
+                                   const struct pipe_box *box)
 {
    struct u_resource *ur = u_resource(transfer->resource);
    ur->vtbl->transfer_flush_region(pipe, transfer, box);
 }
 
 void u_transfer_unmap_vtbl( struct pipe_context *pipe,
-			    struct pipe_transfer *transfer )
+                            struct pipe_transfer *transfer )
 {
    struct u_resource *ur = u_resource(transfer->resource);
    ur->vtbl->transfer_unmap(pipe, transfer);
 }
 
 void u_transfer_inline_write_vtbl( struct pipe_context *pipe,
-				   struct pipe_resource *resource,
-				   struct pipe_subresource sr,
-				   unsigned usage,
-				   const struct pipe_box *box,
-				   const void *data,
-				   unsigned stride,
-				   unsigned slice_stride)
+                                   struct pipe_resource *resource,
+                                   unsigned level,
+                                   unsigned usage,
+                                   const struct pipe_box *box,
+                                   const void *data,
+                                   unsigned stride,
+                                   unsigned layer_stride)
 {
    struct u_resource *ur = u_resource(resource);
-   ur->vtbl->transfer_inline_write(pipe, 
-				   resource,
-				   sr,
-				   usage,
-				   box,
-				   data,
-				   stride,
-				   slice_stride);
+   ur->vtbl->transfer_inline_write(pipe,
+                                   resource,
+                                   level,
+                                   usage,
+                                   box,
+                                   data,
+                                   stride,
+                                   layer_stride);
 }
 
 
diff --git a/src/gallium/auxiliary/util/u_sampler.c b/src/gallium/auxiliary/util/u_sampler.c
index e77f562..bb26099 100644
--- a/src/gallium/auxiliary/util/u_sampler.c
+++ b/src/gallium/auxiliary/util/u_sampler.c
@@ -40,8 +40,11 @@
     */
 
    view->format = format;
-   view->first_level = 0;
-   view->last_level = texture->last_level;
+   view->u.tex.first_level = 0;
+   view->u.tex.last_level = texture->last_level;
+   view->u.tex.first_layer = 0;
+   view->u.tex.last_layer = texture->target == PIPE_TEXTURE_3D ?
+                               texture->depth0 - 1 : texture->array_size - 1;
    view->swizzle_r = PIPE_SWIZZLE_RED;
    view->swizzle_g = PIPE_SWIZZLE_GREEN;
    view->swizzle_b = PIPE_SWIZZLE_BLUE;
diff --git a/src/gallium/auxiliary/util/u_simple_screen.h b/src/gallium/auxiliary/util/u_simple_screen.h
index b52232f..7139aaa 100644
--- a/src/gallium/auxiliary/util/u_simple_screen.h
+++ b/src/gallium/auxiliary/util/u_simple_screen.h
@@ -57,7 +57,8 @@
     * displayed, eg copy fake frontbuffer.
     */
    void (*flush_frontbuffer)( struct pipe_winsys *ws,
-                              struct pipe_surface *surf,
+                              struct pipe_resource *resource,
+                              unsigned level, unsigned layer,
                               void *context_private );
 
 
diff --git a/src/gallium/auxiliary/util/u_staging.c b/src/gallium/auxiliary/util/u_staging.c
index c5d68f8..b6bf241 100644
--- a/src/gallium/auxiliary/util/u_staging.c
+++ b/src/gallium/auxiliary/util/u_staging.c
@@ -41,6 +41,7 @@
    template->width0 = width;
    template->height0 = height;
    template->depth0 = depth;
+   template->array_size = 1;
    template->last_level = 0;
    template->nr_samples = pt->nr_samples;
    template->bind = 0;
@@ -51,7 +52,7 @@
 struct util_staging_transfer *
 util_staging_transfer_init(struct pipe_context *pipe,
            struct pipe_resource *pt,
-           struct pipe_subresource sr,
+           unsigned level,
            unsigned usage,
            const struct pipe_box *box,
            bool direct, struct util_staging_transfer *tx)
@@ -61,7 +62,7 @@
    struct pipe_resource staging_resource_template;
 
    pipe_resource_reference(&tx->base.resource, pt);
-   tx->base.sr = sr;
+   tx->base.level = level;
    tx->base.usage = usage;
    tx->base.box = *box;
 
@@ -82,12 +83,20 @@
 
    if (usage & PIPE_TRANSFER_READ)
    {
-      struct pipe_subresource dstsr;
+      /* XXX this looks wrong dst is always the same but looping over src z? */
       unsigned zi;
-      dstsr.face = 0;
-      dstsr.level = 0;
-      for(zi = 0; zi < box->depth; ++zi)
-         pipe->resource_copy_region(pipe, tx->staging_resource, dstsr, 0, 0, 0, tx->base.resource, sr, box->x, box->y, box->z + zi, box->width, box->height);
+      struct pipe_box sbox;
+      sbox.x = box->x;
+      sbox.y = box->y;
+      sbox.z = box->z;
+      sbox.width = box->width;
+      sbox.height = box->height;
+      sbox.depth = 1;
+      for(zi = 0; zi < box->depth; ++zi) {
+         sbox.z = sbox.z + zi;
+         pipe->resource_copy_region(pipe, tx->staging_resource, 0, 0, 0, 0,
+                                    tx->base.resource, level, &sbox);
+      }
    }
 
    return tx;
@@ -101,12 +110,18 @@
    if (tx->staging_resource != tx->base.resource)
    {
       if(tx->base.usage & PIPE_TRANSFER_WRITE) {
-         struct pipe_subresource srcsr;
+         /* XXX this looks wrong src is always the same but looping over dst z? */
          unsigned zi;
-         srcsr.face = 0;
-         srcsr.level = 0;
+         struct pipe_box sbox;
+         sbox.x = 0;
+         sbox.y = 0;
+         sbox.z = 0;
+         sbox.width = tx->base.box.width;
+         sbox.height = tx->base.box.height;
+         sbox.depth = 1;
          for(zi = 0; zi < tx->base.box.depth; ++zi)
-            pipe->resource_copy_region(pipe, tx->base.resource, tx->base.sr, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi, tx->staging_resource, srcsr, 0, 0, 0, tx->base.box.width, tx->base.box.height);
+            pipe->resource_copy_region(pipe, tx->base.resource, tx->base.level, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi,
+                                       tx->staging_resource, 0, &sbox);
       }
 
       pipe_resource_reference(&tx->staging_resource, NULL);
diff --git a/src/gallium/auxiliary/util/u_staging.h b/src/gallium/auxiliary/util/u_staging.h
index 1aab78c..49839d2 100644
--- a/src/gallium/auxiliary/util/u_staging.h
+++ b/src/gallium/auxiliary/util/u_staging.h
@@ -52,7 +52,7 @@
 struct util_staging_transfer *
 util_staging_transfer_init(struct pipe_context *pipe,
            struct pipe_resource *pt,
-           struct pipe_subresource sr,
+           unsigned level,
            unsigned usage,
            const struct pipe_box *box,
            bool direct, struct util_staging_transfer *tx);
diff --git a/src/gallium/auxiliary/util/u_surface.c b/src/gallium/auxiliary/util/u_surface.c
index f78b683..4eddd3f 100644
--- a/src/gallium/auxiliary/util/u_surface.c
+++ b/src/gallium/auxiliary/util/u_surface.c
@@ -42,6 +42,18 @@
 #include "util/u_surface.h"
 #include "util/u_pack_color.h"
 
+void
+u_surface_default_template(struct pipe_surface *view,
+                           const struct pipe_resource *texture,
+                           unsigned bind)
+{
+   view->format = texture->format;
+   view->u.tex.level = 0;
+   view->u.tex.first_layer = 0;
+   view->u.tex.last_layer = 0;
+   /* XXX should filter out all non-rt/ds bind flags ? */
+   view->usage = bind;
+}
 
 /**
  * Helper to quickly create an RGBA rendering surface of a certain size.
@@ -50,9 +62,9 @@
  * \return TRUE for success, FALSE if failure
  */
 boolean
-util_create_rgba_surface(struct pipe_screen *screen,
+util_create_rgba_surface(struct pipe_context *pipe,
                          uint width, uint height,
-			 uint bind,
+                         uint bind,
                          struct pipe_resource **textureOut,
                          struct pipe_surface **surfaceOut)
 {
@@ -65,6 +77,8 @@
    const uint target = PIPE_TEXTURE_2D;
    enum pipe_format format = PIPE_FORMAT_NONE;
    struct pipe_resource templ;
+   struct pipe_surface surf_templ;
+   struct pipe_screen *screen = pipe->screen;
    uint i;
 
    /* Choose surface format */
@@ -86,17 +100,20 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.bind = bind;
 
    *textureOut = screen->resource_create(screen, &templ);
    if (!*textureOut)
       return FALSE;
 
+   /* create surface */
+   memset(&surf_templ, 0, sizeof(surf_templ));
+   u_surface_default_template(&surf_templ, *textureOut, bind);
    /* create surface / view into texture */
-   *surfaceOut = screen->get_tex_surface(screen, 
-					 *textureOut,
-					 0, 0, 0,
-					 bind);
+   *surfaceOut = pipe->create_surface(pipe,
+                                      *textureOut,
+                                      &surf_templ);
    if (!*surfaceOut) {
       pipe_resource_reference(textureOut, NULL);
       return FALSE;
@@ -126,17 +143,18 @@
 void
 util_resource_copy_region(struct pipe_context *pipe,
                           struct pipe_resource *dst,
-                          struct pipe_subresource subdst,
+                          unsigned dst_level,
                           unsigned dst_x, unsigned dst_y, unsigned dst_z,
                           struct pipe_resource *src,
-                          struct pipe_subresource subsrc,
-                          unsigned src_x, unsigned src_y, unsigned src_z,
-                          unsigned w, unsigned h)
+                          unsigned src_level,
+                          const struct pipe_box *src_box)
 {
    struct pipe_transfer *src_trans, *dst_trans;
    void *dst_map;
    const void *src_map;
    enum pipe_format src_format, dst_format;
+   unsigned w = src_box->width;
+   unsigned h = src_box->height;
 
    assert(src && dst);
    if (!src || !dst)
@@ -146,20 +164,18 @@
    dst_format = dst->format;
 
    src_trans = pipe_get_transfer(pipe,
-				 src,
-				 subsrc.face,
-				 subsrc.level,
-				 src_z,
-				 PIPE_TRANSFER_READ,
-				 src_x, src_y, w, h);
+                                 src,
+                                 src_level,
+                                 src_box->z,
+                                 PIPE_TRANSFER_READ,
+                                 src_box->x, src_box->y, w, h);
 
    dst_trans = pipe_get_transfer(pipe,
-				 dst,
-				 subdst.face,
-				 subdst.level,
-				 src_z,
-				 PIPE_TRANSFER_WRITE,
-				 dst_x, dst_y, w, h);
+                                 dst,
+                                 dst_level,
+                                 dst_z,
+                                 PIPE_TRANSFER_WRITE,
+                                 dst_x, dst_y, w, h);
 
    assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
    assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
@@ -216,14 +232,13 @@
    assert(dst->texture);
    if (!dst->texture)
       return;
-
+   /* XXX: should handle multiple layers */
    dst_trans = pipe_get_transfer(pipe,
-				 dst->texture,
-				 dst->face,
-				 dst->level,
-				 dst->zslice,
-				 PIPE_TRANSFER_WRITE,
-				 dstx, dsty, width, height);
+                                 dst->texture,
+                                 dst->u.tex.level,
+                                 dst->u.tex.first_layer,
+                                 PIPE_TRANSFER_WRITE,
+                                 dstx, dsty, width, height);
 
    dst_map = pipe->transfer_map(pipe, dst_trans);
 
@@ -271,9 +286,8 @@
       return;
    dst_trans = pipe_get_transfer(pipe,
                                  dst->texture,
-                                 dst->face,
-                                 dst->level,
-                                 dst->zslice,
+                                 dst->u.tex.level,
+                                 dst->u.tex.first_layer,
                                  (need_rmw ? PIPE_TRANSFER_READ_WRITE :
                                      PIPE_TRANSFER_WRITE),
                                  dstx, dsty, width, height);
diff --git a/src/gallium/auxiliary/util/u_surface.h b/src/gallium/auxiliary/util/u_surface.h
index 6cd12af..6b82e14 100644
--- a/src/gallium/auxiliary/util/u_surface.h
+++ b/src/gallium/auxiliary/util/u_surface.h
@@ -32,9 +32,13 @@
 #include "pipe/p_compiler.h"
 #include "pipe/p_state.h"
 
+extern void
+u_surface_default_template(struct pipe_surface *view,
+                           const struct pipe_resource *texture,
+                           unsigned bind);
 
 extern boolean
-util_create_rgba_surface(struct pipe_screen *screen,
+util_create_rgba_surface(struct pipe_context *ctx,
                          uint width, uint height, uint bind,
                          struct pipe_resource **textureOut,
                          struct pipe_surface **surfaceOut);
@@ -49,12 +53,11 @@
 extern void
 util_resource_copy_region(struct pipe_context *pipe,
                           struct pipe_resource *dst,
-                          struct pipe_subresource subdst,
+                          unsigned dst_level,
                           unsigned dst_x, unsigned dst_y, unsigned dst_z,
                           struct pipe_resource *src,
-                          struct pipe_subresource subsrc,
-                          unsigned src_x, unsigned src_y, unsigned src_z,
-                          unsigned w, unsigned h);
+                          unsigned src_level,
+                          const struct pipe_box *src_box);
 
 extern void
 util_clear_render_target(struct pipe_context *pipe,
diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c
index 404e121..45aa15e 100644
--- a/src/gallium/auxiliary/util/u_surfaces.c
+++ b/src/gallium/auxiliary/util/u_surfaces.c
@@ -30,7 +30,9 @@
 #include "util/u_memory.h"
 
 struct pipe_surface *
-util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
+util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size,
+                     struct pipe_screen *pscreen, struct pipe_resource *pt,
+                     unsigned level, unsigned layer, unsigned flags)
 {
    struct pipe_surface *ps;
 
@@ -39,7 +41,7 @@
       if(!us->u.hash)
          us->u.hash = cso_hash_create();
 
-      ps = cso_hash_iter_data(cso_hash_find(us->u.hash, ((zslice + face) << 8) | level));
+      ps = cso_hash_iter_data(cso_hash_find(us->u.hash, (layer << 8) | level));
    }
    else
    {
@@ -58,11 +60,10 @@
    if(!ps)
       return NULL;
 
-   pipe_surface_init(ps, pt, face, level, zslice, flags);
-   ps->offset = ~0;
+   pipe_surface_init(ps, pt, level, layer, flags);
 
    if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
-      cso_hash_insert(us->u.hash, ((zslice + face) << 8) | level, ps);
+      cso_hash_insert(us->u.hash, (layer << 8) | level, ps);
    else
       us->u.array[level] = ps;
 
@@ -75,10 +76,10 @@
    struct pipe_resource *pt = ps->texture;
    if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
    {    /* or 2D array */
-      cso_hash_erase(us->u.hash, cso_hash_find(us->u.hash, ((ps->zslice + ps->face) << 8) | ps->level));
+      cso_hash_erase(us->u.hash, cso_hash_find(us->u.hash, (ps->u.tex.first_layer << 8) | ps->u.tex.level));
    }
    else
-      us->u.array[ps->level] = 0;
+      us->u.array[ps->u.tex.level] = 0;
 }
 
 void
diff --git a/src/gallium/auxiliary/util/u_surfaces.h b/src/gallium/auxiliary/util/u_surfaces.h
index 17d8a5d..86a1c2f 100644
--- a/src/gallium/auxiliary/util/u_surfaces.h
+++ b/src/gallium/auxiliary/util/u_surfaces.h
@@ -42,11 +42,11 @@
    } u;
 };
 
-struct pipe_surface *util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags);
+struct pipe_surface *util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned level, unsigned layer, unsigned flags);
 
 /* fast inline path for the very common case */
 static INLINE struct pipe_surface *
-util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags)
+util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned level, unsigned layer, unsigned flags)
 {
    if(likely((pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT) && us->u.array))
    {
@@ -58,17 +58,17 @@
       }
    }
 
-   return util_surfaces_do_get(us, surface_struct_size, pscreen, pt, face, level, zslice, flags);
+   return util_surfaces_do_get(us, surface_struct_size, pscreen, pt, level, layer, flags);
 }
 
 static INLINE struct pipe_surface *
-util_surfaces_peek(struct util_surfaces *us, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice)
+util_surfaces_peek(struct util_surfaces *us, struct pipe_resource *pt, unsigned level, unsigned layer)
 {
    if(!us->u.pv)
       return 0;
 
    if(unlikely(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE))
-      return cso_hash_iter_data(cso_hash_find(us->u.hash, ((zslice + face) << 8) | level));
+      return cso_hash_iter_data(cso_hash_find(us->u.hash, (layer << 8) | level));
    else
       return us->u.array[level];
 }
@@ -80,7 +80,7 @@
 {
    if(likely(ps->texture->target == PIPE_TEXTURE_2D || ps->texture->target == PIPE_TEXTURE_RECT))
    {
-      us->u.array[ps->level] = 0;
+      us->u.array[ps->u.tex.level] = 0;
       return;
    }
 
diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c
index 69f6fab..e2828cf 100644
--- a/src/gallium/auxiliary/util/u_transfer.c
+++ b/src/gallium/auxiliary/util/u_transfer.c
@@ -8,22 +8,24 @@
  * pointer.  XXX: strides??
  */
 void u_default_transfer_inline_write( struct pipe_context *pipe,
-				      struct pipe_resource *resource,
-				      struct pipe_subresource sr,
-				      unsigned usage,
-				      const struct pipe_box *box,
-				      const void *data,
-				      unsigned stride,
-				      unsigned slice_stride)
+                                      struct pipe_resource *resource,
+                                      unsigned level,
+                                      unsigned usage,
+                                      const struct pipe_box *box,
+                                      const void *data,
+                                      unsigned stride,
+                                      unsigned layer_stride)
 {
    struct pipe_transfer *transfer = NULL;
    uint8_t *map = NULL;
+   const uint8_t *src_data = data;
+   unsigned i;
 
-   transfer = pipe->get_transfer(pipe, 
-				 resource,
-				 sr,
-				 usage,
-				 box );
+   transfer = pipe->get_transfer(pipe,
+                                 resource,
+                                 level,
+                                 usage,
+                                 box );
    if (transfer == NULL)
       goto out;
 
@@ -31,17 +33,19 @@
    if (map == NULL)
       goto out;
 
-   assert(box->depth == 1);	/* XXX: fix me */
-   
-   util_copy_rect(map,
-		  resource->format,
-		  transfer->stride, /* bytes */
-		  0, 0,
-		  box->width,
-		  box->height,
-		  data,
-		  stride,       /* bytes */
-		  0, 0);
+   for (i = 0; i < box->depth; i++) {
+      util_copy_rect(map,
+                     resource->format,
+                     transfer->stride, /* bytes */
+                     0, 0,
+                     box->width,
+                     box->height,
+                     src_data,
+                     stride,       /* bytes */
+                     0, 0);
+      map += transfer->layer_stride;
+      src_data += layer_stride;
+   }
 
 out:
    if (map)
@@ -53,8 +57,8 @@
 
 
 boolean u_default_resource_get_handle(struct pipe_screen *screen,
-				      struct pipe_resource *resource,
-				      struct winsys_handle *handle)
+                                      struct pipe_resource *resource,
+                                      struct winsys_handle *handle)
 {
    return FALSE;
 }
@@ -62,32 +66,32 @@
 
 
 void u_default_transfer_flush_region( struct pipe_context *pipe,
-				      struct pipe_transfer *transfer,
-				      const struct pipe_box *box)
+                                      struct pipe_transfer *transfer,
+                                      const struct pipe_box *box)
 {
    /* This is a no-op implementation, nothing to do.
     */
 }
 
 unsigned u_default_is_resource_referenced( struct pipe_context *pipe,
-					   struct pipe_resource *resource,
-					unsigned face, unsigned level)
+                                           struct pipe_resource *resource,
+                                           unsigned level, int layer)
 {
    return 0;
 }
 
 struct pipe_transfer * u_default_get_transfer(struct pipe_context *context,
-					      struct pipe_resource *resource,
-					      struct pipe_subresource sr,
-					      unsigned usage,
-					      const struct pipe_box *box)
+                                              struct pipe_resource *resource,
+                                              unsigned level,
+                                              unsigned usage,
+                                              const struct pipe_box *box)
 {
    struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
    if (transfer == NULL)
       return NULL;
 
    transfer->resource = resource;
-   transfer->sr = sr;
+   transfer->level = level;
    transfer->usage = usage;
    transfer->box = *box;
 
@@ -98,12 +102,12 @@
 }
 
 void u_default_transfer_unmap( struct pipe_context *pipe,
-			      struct pipe_transfer *transfer )
+                               struct pipe_transfer *transfer )
 {
 }
 
 void u_default_transfer_destroy(struct pipe_context *pipe,
-				struct pipe_transfer *transfer)
+                                struct pipe_transfer *transfer)
 {
    FREE(transfer);
 }
diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h
index e3a3873..3412e13 100644
--- a/src/gallium/auxiliary/util/u_transfer.h
+++ b/src/gallium/auxiliary/util/u_transfer.h
@@ -11,37 +11,37 @@
 struct winsys_handle;
 
 boolean u_default_resource_get_handle(struct pipe_screen *screen,
-				      struct pipe_resource *resource,
-				      struct winsys_handle *handle);
+                                      struct pipe_resource *resource,
+                                      struct winsys_handle *handle);
 
 void u_default_transfer_inline_write( struct pipe_context *pipe,
-			      struct pipe_resource *resource,
-			      struct pipe_subresource sr,
-			      unsigned usage,
-			      const struct pipe_box *box,
-			      const void *data,
-			      unsigned stride,
-			      unsigned slice_stride);
+                                      struct pipe_resource *resource,
+                                      unsigned level,
+                                      unsigned usage,
+                                      const struct pipe_box *box,
+                                      const void *data,
+                                      unsigned stride,
+                                      unsigned layer_stride);
 
 void u_default_transfer_flush_region( struct pipe_context *pipe,
-				      struct pipe_transfer *transfer,
-				      const struct pipe_box *box);
+                                      struct pipe_transfer *transfer,
+                                      const struct pipe_box *box);
 
 unsigned u_default_is_resource_referenced( struct pipe_context *pipe,
-					   struct pipe_resource *resource,
-					   unsigned face, unsigned level);
+                                           struct pipe_resource *resource,
+                                           unsigned level, int layer);
 
 struct pipe_transfer * u_default_get_transfer(struct pipe_context *context,
-					      struct pipe_resource *resource,
-					      struct pipe_subresource sr,
-					      unsigned usage,
-					      const struct pipe_box *box);
+                                              struct pipe_resource *resource,
+                                              unsigned level,
+                                              unsigned usage,
+                                              const struct pipe_box *box);
 
 void u_default_transfer_unmap( struct pipe_context *pipe,
-			       struct pipe_transfer *transfer );
+                               struct pipe_transfer *transfer );
 
 void u_default_transfer_destroy(struct pipe_context *pipe,
-				struct pipe_transfer *transfer);
+                                struct pipe_transfer *transfer);
 
 
 
@@ -51,43 +51,43 @@
 struct u_resource_vtbl {
 
    boolean (*resource_get_handle)(struct pipe_screen *,
-				  struct pipe_resource *tex,
-				  struct winsys_handle *handle);
+                                  struct pipe_resource *tex,
+                                  struct winsys_handle *handle);
 
    void (*resource_destroy)(struct pipe_screen *,
-			    struct pipe_resource *pt);
+                            struct pipe_resource *pt);
 
    unsigned (*is_resource_referenced)(struct pipe_context *pipe,
-				      struct pipe_resource *texture,
-				      unsigned face, unsigned level);
+                                      struct pipe_resource *texture,
+                                      unsigned level, int layer);
 
    struct pipe_transfer *(*get_transfer)(struct pipe_context *,
-					 struct pipe_resource *resource,
-					 struct pipe_subresource,
-					 unsigned usage,
-					 const struct pipe_box *);
+                                         struct pipe_resource *resource,
+                                         unsigned level,
+                                         unsigned usage,
+                                         const struct pipe_box *);
 
    void (*transfer_destroy)(struct pipe_context *,
-			    struct pipe_transfer *);
+                            struct pipe_transfer *);
 
    void *(*transfer_map)( struct pipe_context *,
-			  struct pipe_transfer *transfer );
+                          struct pipe_transfer *transfer );
 
    void (*transfer_flush_region)( struct pipe_context *,
-				  struct pipe_transfer *transfer,
-				  const struct pipe_box *);
+                                  struct pipe_transfer *transfer,
+                                  const struct pipe_box *);
 
    void (*transfer_unmap)( struct pipe_context *,
-			   struct pipe_transfer *transfer );
+   struct pipe_transfer *transfer );
 
    void (*transfer_inline_write)( struct pipe_context *pipe,
-				  struct pipe_resource *resource,
-				  struct pipe_subresource sr,
-				  unsigned usage,
-				  const struct pipe_box *box,
-				  const void *data,
-				  unsigned stride,
-				  unsigned slice_stride);
+                                  struct pipe_resource *resource,
+                                  unsigned level,
+                                  unsigned usage,
+                                  const struct pipe_box *box,
+                                  const void *data,
+                                  unsigned stride,
+                                  unsigned layer_stride);
 };
 
 
@@ -98,43 +98,43 @@
 
 
 boolean u_resource_get_handle_vtbl(struct pipe_screen *screen,
-			      struct pipe_resource *resource,
-			      struct winsys_handle *handle);
+                                   struct pipe_resource *resource,
+                                   struct winsys_handle *handle);
 
 void u_resource_destroy_vtbl(struct pipe_screen *screen,
-			struct pipe_resource *resource);
+                             struct pipe_resource *resource);
 
 unsigned u_is_resource_referenced_vtbl( struct pipe_context *pipe,
-					struct pipe_resource *resource,
-					unsigned face, unsigned level);
+                                        struct pipe_resource *resource,
+                                        unsigned level, int layer);
 
 struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context,
-				     struct pipe_resource *resource,
-				     struct pipe_subresource sr,
-				     unsigned usage,
-				     const struct pipe_box *box);
+                                          struct pipe_resource *resource,
+                                          unsigned level,
+                                          unsigned usage,
+                                          const struct pipe_box *box);
 
 void u_transfer_destroy_vtbl(struct pipe_context *pipe,
-			struct pipe_transfer *transfer);
+                             struct pipe_transfer *transfer);
 
 void *u_transfer_map_vtbl( struct pipe_context *pipe,
-		      struct pipe_transfer *transfer );
+                           struct pipe_transfer *transfer );
 
 void u_transfer_flush_region_vtbl( struct pipe_context *pipe,
-			      struct pipe_transfer *transfer,
-			      const struct pipe_box *box);
+                                   struct pipe_transfer *transfer,
+                                   const struct pipe_box *box);
 
 void u_transfer_unmap_vtbl( struct pipe_context *rm_ctx,
-		       struct pipe_transfer *transfer );
+                            struct pipe_transfer *transfer );
 
 void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx,
-				   struct pipe_resource *resource,
-				   struct pipe_subresource sr,
-				   unsigned usage,
-				   const struct pipe_box *box,
-				   const void *data,
-				   unsigned stride,
-				   unsigned slice_stride);
+                                   struct pipe_resource *resource,
+                                   unsigned level,
+                                   unsigned usage,
+                                   const struct pipe_box *box,
+                                   const void *data,
+                                   unsigned stride,
+                                   unsigned layer_stride);
 
 
 
diff --git a/src/gallium/docs/d3d11ddi.txt b/src/gallium/docs/d3d11ddi.txt
index f8155c8..11e7719 100644
--- a/src/gallium/docs/d3d11ddi.txt
+++ b/src/gallium/docs/d3d11ddi.txt
@@ -162,8 +162,8 @@
 	+ Gallium has per-face writemask/valuemasks, D3D11 uses the same value for back and front
 	+ Gallium supports the alpha test, which D3D11 lacks
 
-CreateDepthStencilView -> get_tex_surface
-CreateRenderTargetView -> get_tex_surface
+CreateDepthStencilView -> create_surface
+CreateRenderTargetView -> create_surface
 	! Gallium merges depthstencil and rendertarget views into pipe_surface, which also doubles as a 2D surface abstraction
 	- lack of texture array support
 	- lack of render-to-buffer support
@@ -221,7 +221,6 @@
 	! D3D11 specifies mapping flags (i.e. read/write/discard);:it's unclear what they are used for here
 	- D3D11 supports odd things in the D3D10_DDI_RESOURCE_MISC_FLAG enum (D3D10_DDI_RESOURCE_MISC_DISCARD_ON_PRESENT, D3D11_DDI_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS, D3D11_DDI_RESOURCE_MISC_BUFFER_STRUCTURED)
 	- Gallium does not support indirect draw call parameter buffers
-	- Gallium lacks array textures
 	! D3D11 supports specifying hardware modes and other stuff here for scanout resources
 	+ Gallium allows specifying minimum buffer alignment
 	! D3D11 implements cube maps as 2D array textures
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index e09a130..c33cf7c 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -84,7 +84,14 @@
 placed in first component of result register.
 
 The ``first_level`` and ``last_level`` fields of sampler view template specify
-the LOD range the texture is going to be constrained to.
+the LOD range the texture is going to be constrained to. Note that these
+values are in addition to the respective min_lod, max_lod values in the
+pipe_sampler_state (that is if min_lod is 2.0, and first_level 3, the first mip
+level used for sampling from the resource is effectively the fifth).
+
+The ``first_layer`` and ``last_layer`` fields specify the layer range the
+texture is going to be constrained to. Similar to the LOD range, this is added
+to the array index which is used for sampling.
 
 * ``set_fragment_sampler_views`` binds an array of sampler views to
   fragment shader stage. Every binding point acquires a reference
@@ -103,6 +110,22 @@
 * ``sampler_view_destroy`` destroys a sampler view and releases its reference
   to associated texture.
 
+Surfaces
+^^^^^^^^
+
+These are the means to use resources as color render targets or depthstencil
+attachments. To create one, specify the mip level, the range of layers, and
+the bind flags (either PIPE_BIND_DEPTH_STENCIL or PIPE_BIND_RENDER_TARGET).
+Note that layer values are in addition to what is indicated by the geometry
+shader output variable XXX_FIXME (that is if first_layer is 3 and geometry
+shader indicates index 2, the 5th layer of the resource will be used). These
+first_layer and last_layer parameters will only be used for 1d array, 2d array,
+cube, and 3d textures otherwise they are 0.
+
+* ``create_surface`` creates a new surface.
+
+* ``surface_destroy`` destroys a surface and releases its reference to the
+  associated resource.
 
 Clearing
 ^^^^^^^^
@@ -118,8 +141,7 @@
 GL clear or explicit rectangles like d3d9 uses). It can, however, also clear
 only depth or stencil in a combined depth/stencil surface, if the driver
 supports PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE.
-If a surface includes several layers/slices (XXX: not yet...) then all layers
-will be cleared.
+If a surface includes several layers then all layers will be cleared.
 
 ``clear_render_target`` clears a single color rendertarget with the specified
 color value. While it is only possible to clear one surface at a time (which can
@@ -271,12 +293,12 @@
 apart from any 3D state in the context.  Blitting functionality may be
 moved to a separate abstraction at some point in the future.
 
-``resource_copy_region`` blits a region of a subresource of a resource to a
-region of another subresource of a resource, provided that both resources have
-the same format, or compatible formats, i.e., formats for which copying the
-bytes from the source resource unmodified to the destination resource will
-achieve the same effect of a textured quad blitter. The source and destination
-may be the same resource, but overlapping blits are not permitted.
+``resource_copy_region`` blits a region of a resource to a region of another
+resource, provided that both resources have the same format, or compatible
+formats, i.e., formats for which copying the bytes from the source resource
+unmodified to the destination resource will achieve the same effect of a
+textured quad blitter.. The source and destination may be the same resource,
+but overlapping blits are not permitted.
 
 ``resource_resolve`` resolves a multisampled resource into a non-multisampled
 one. Formats and dimensions must match. This function must be present if a driver
diff --git a/src/gallium/docs/source/glossary.rst b/src/gallium/docs/source/glossary.rst
index acde56e..c749d0c 100644
--- a/src/gallium/docs/source/glossary.rst
+++ b/src/gallium/docs/source/glossary.rst
@@ -22,6 +22,14 @@
       Level of Detail. Also spelled "LoD." The value that determines when the
       switches between mipmaps occur during texture sampling.
 
+   layer
+      This term is used as the name of the "3rd coordinate" of a resource.
+      3D textures have zslices, cube maps have faces, 1D and 2D array textures
+      have array members (other resources do not have multiple layers).
+      Since the functions only take one parameter no matter what type of
+      resource is used, use the term "layer" instead of a resource type
+      specific one.
+
    GLSL
       GL Shading Language. The official, common high-level shader language used
       in GL 2.0 and above.
diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst
index e3ef49c..09edbaa 100644
--- a/src/gallium/docs/source/screen.rst
+++ b/src/gallium/docs/source/screen.rst
@@ -258,25 +258,33 @@
 Create a new resource from a template.
 The following fields of the pipe_resource must be specified in the template:
 
-target
+**target** one of the pipe_texture_target enums.
+Note that PIPE_BUFFER and PIPE_TEXTURE_X are not really fundamentally different.
+Modern APIs allow using buffers as shader resources.
 
-format
+**format** one of the pipe_format enums.
 
-width0
+**width0** the width of the base mip level of the texture or size of the buffer.
 
-height0
+**height0** the height of the base mip level of the texture
+(1 for 1D or 1D array textures).
 
-depth0
+**depth0** the depth of the base mip level of the texture
+(1 for everything else).
 
-last_level
+**array_size the array size for 1D and 2D array textures.
+For cube maps this must be 6, for other textures 1.
 
-nr_samples
+**last_level** the last mip map level present.
 
-usage
+**nr_samples** the nr of msaa samples. 0 (or 1) specifies a resource
+which isn't multisampled.
 
-bind
+**usage** one of the PIPE_USAGE flags.
 
-flags
+**bind** bitmask of the PIPE_BIND flags.
+
+**flags** bitmask of PIPE_RESOURCE_FLAG flags.
 
 
 
diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c
index 143eca8..b6b3a70 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.c
+++ b/src/gallium/drivers/cell/ppu/cell_context.c
@@ -100,8 +100,8 @@
 
 static unsigned int
 cell_is_resource_referenced( struct pipe_context *pipe,
-			    struct pipe_resource *texture,
-			    unsigned face, unsigned level)
+                             struct pipe_resource *texture,
+                             unsigned level, int layer)
 {
    /**
     * FIXME: Optimize.
diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c
index b3042df..946a705 100644
--- a/src/gallium/drivers/cell/ppu/cell_texture.c
+++ b/src/gallium/drivers/cell/ppu/cell_texture.c
@@ -304,47 +304,34 @@
 
 
 static struct pipe_surface *
-cell_get_tex_surface(struct pipe_screen *screen,
-                     struct pipe_resource *pt,
-                     unsigned face, unsigned level, unsigned zslice,
-                     unsigned usage)
+cell_create_surface(struct pipe_context *ctx,
+                    struct pipe_resource *pt,
+                    const struct pipe_surface *surf_tmpl)
 {
    struct cell_resource *ct = cell_resource(pt);
    struct pipe_surface *ps;
 
+   assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
    ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
       pipe_reference_init(&ps->reference, 1);
       pipe_resource_reference(&ps->texture, pt);
-      ps->format = pt->format;
-      ps->width = u_minify(pt->width0, level);
-      ps->height = u_minify(pt->height0, level);
-      ps->offset = ct->level_offset[level];
+      ps->format = surf_tmpl->format;
+      ps->context = ctx;
+      ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
+      ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
       /* XXX may need to override usage flags (see sp_texture.c) */
-      ps->usage = usage;
-      ps->face = face;
-      ps->level = level;
-      ps->zslice = zslice;
-
-      if (pt->target == PIPE_TEXTURE_CUBE) {
-         unsigned h_tile = align(ps->height, TILE_SIZE);
-         ps->offset += face * util_format_get_nblocksy(ps->format, h_tile) * ct->stride[level];
-      }
-      else if (pt->target == PIPE_TEXTURE_3D) {
-         unsigned h_tile = align(ps->height, TILE_SIZE);
-         ps->offset += zslice * util_format_get_nblocksy(ps->format, h_tile) * ct->stride[level];
-      }
-      else {
-         assert(face == 0);
-         assert(zslice == 0);
-      }
+      ps->usage = surf_tmpl->usage;
+      ps->u.tex.level = surf_tmpl->u.tex.level;
+      ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+      ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
    }
    return ps;
 }
 
 
 static void 
-cell_tex_surface_destroy(struct pipe_surface *surf)
+cell_surface_destroy(struct pipe_context *ctx, struct pipe_surface *surf)
 {
    pipe_resource_reference(&surf->texture, NULL);
    FREE(surf);
@@ -358,44 +345,39 @@
  */
 static struct pipe_transfer *
 cell_get_transfer(struct pipe_context *ctx,
-		  struct pipe_resource *resource,
-		  struct pipe_subresource sr,
-		  unsigned usage,
-		  const struct pipe_box *box)
+                  struct pipe_resource *resource,
+                  unsigned level,
+                  unsigned usage,
+                  const struct pipe_box *box)
 {
    struct cell_resource *ct = cell_resource(resource);
    struct cell_transfer *ctrans;
    enum pipe_format format = resource->format;
 
    assert(resource);
-   assert(sr.level <= resource->last_level);
+   assert(level <= resource->last_level);
 
    /* make sure the requested region is in the image bounds */
-   assert(box->x + box->width <= u_minify(resource->width0, sr.level));
-   assert(box->y + box->height <= u_minify(resource->height0, sr.level));
-   assert(box->z + box->depth <= u_minify(resource->depth0, sr.level));
+   assert(box->x + box->width <= u_minify(resource->width0, level));
+   assert(box->y + box->height <= u_minify(resource->height0, level));
+   assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1));
 
    ctrans = CALLOC_STRUCT(cell_transfer);
    if (ctrans) {
       struct pipe_transfer *pt = &ctrans->base;
       pipe_resource_reference(&pt->resource, resource);
-      pt->sr = sr;
+      pt->level = level;
       pt->usage = usage;
       pt->box = *box;
-      pt->stride = ct->stride[sr.level];
+      pt->stride = ct->stride[level];
 
-      ctrans->offset = ct->level_offset[sr.level];
+      ctrans->offset = ct->level_offset[level];
 
-      if (resource->target == PIPE_TEXTURE_CUBE) {
-         unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE);
-         ctrans->offset += sr.face * util_format_get_nblocksy(format, h_tile) * pt->stride;
-      }
-      else if (resource->target == PIPE_TEXTURE_3D) {
-         unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE);
+      if (resource->target == PIPE_TEXTURE_CUBE || resource->target == PIPE_TEXTURE_3D) {
+         unsigned h_tile = align(u_minify(resource->height0, level), TILE_SIZE);
          ctrans->offset += box->z * util_format_get_nblocksy(format, h_tile) * pt->stride;
       }
       else {
-         assert(sr.face == 0);
          assert(box->z == 0);
       }
 
@@ -439,7 +421,7 @@
    /* Better test would be resource->is_linear
     */
    if (transfer->resource->target != PIPE_BUFFER) {
-      const uint level = ctrans->base.sr.level;
+      const uint level = ctrans->base.level;
       const uint texWidth = u_minify(pt->width0, level);
       const uint texHeight = u_minify(pt->height0, level);
       unsigned size;
@@ -500,7 +482,7 @@
    struct cell_transfer *ctrans = cell_transfer(transfer);
    struct pipe_resource *pt = transfer->resource;
    struct cell_resource *ct = cell_resource(pt);
-   const uint level = ctrans->base.sr.level;
+   const uint level = ctrans->base.level;
    const uint texWidth = u_minify(pt->width0, level);
    const uint texHeight = u_minify(pt->height0, level);
    const uint stride = ct->stride[level];
@@ -548,12 +530,13 @@
  */
 static void
 cell_flush_frontbuffer(struct pipe_screen *_screen,
-                       struct pipe_surface *surface,
+                       struct pipe_resource *resource,
+                       unsigned level, unsigned layer,
                        void *context_private)
 {
    struct cell_screen *screen = cell_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
-   struct cell_resource *ct = cell_resource(surface->texture);
+   struct cell_resource *ct = cell_resource(resource);
 
    if (!ct->dt)
       return;
@@ -564,10 +547,10 @@
       unsigned *map = winsys->displaytarget_map(winsys, ct->dt,
                                                 (PIPE_TRANSFER_READ |
                                                  PIPE_TRANSFER_WRITE));
-      unsigned *src = (unsigned *)(ct->data + ct->level_offset[surface->level]);
+      unsigned *src = (unsigned *)(ct->data + ct->level_offset[level]);
 
-      untwiddle_image_uint(surface->width,
-                           surface->height,
+      untwiddle_image_uint(u_minify(resource->width0, level),
+                           u_minify(resource->height0, level),
                            TILE_SIZE,
                            map,
                            ct->dt_stride,
@@ -605,6 +588,7 @@
    buffer->base.width0 = bytes;
    buffer->base.height0 = 1;
    buffer->base.depth0 = 1;
+   buffer->base.array_size = 1;
    buffer->userBuffer = TRUE;
    buffer->data = ptr;
 
@@ -641,9 +625,6 @@
    screen->resource_get_handle = cell_resource_get_handle;
    screen->user_buffer_create = cell_user_buffer_create;
 
-   screen->get_tex_surface = cell_get_tex_surface;
-   screen->tex_surface_destroy = cell_tex_surface_destroy;
-
    screen->flush_frontbuffer = cell_flush_frontbuffer;
 }
 
@@ -657,4 +638,7 @@
 
    cell->pipe.transfer_flush_region = u_default_transfer_flush_region;
    cell->pipe.transfer_inline_write = u_default_transfer_inline_write;
+
+   cell->pipe.create_surface = cell_create_surface;
+   cell->pipe.surface_destroy = cell_surface_destroy;
 }
diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c
index ec36092..e4d289c 100644
--- a/src/gallium/drivers/failover/fo_context.c
+++ b/src/gallium/drivers/failover/fo_context.c
@@ -89,14 +89,14 @@
 
 static unsigned int
 failover_is_resource_referenced( struct pipe_context *_pipe,
-				 struct pipe_resource *resource,
-				 unsigned face, unsigned level)
+                                 struct pipe_resource *resource,
+                                 unsigned level, int layer)
 {
    struct failover_context *failover = failover_context( _pipe );
    struct pipe_context *pipe = (failover->mode == FO_HW) ?
       failover->hw : failover->sw;
 
-   return pipe->is_resource_referenced(pipe, resource, face, level);
+   return pipe->is_resource_referenced(pipe, resource, level, layer);
 }
 
 struct pipe_context *failover_create( struct pipe_context *hw,
@@ -137,10 +137,10 @@
    failover->pipe.resource_copy_region = hw->resource_copy_region;
 
 #if 0
-   failover->pipe.texture_create = hw->texture_create;
-   failover->pipe.texture_destroy = hw->texture_destroy;
-   failover->pipe.get_tex_surface = hw->get_tex_surface;
-   failover->pipe.texture_update = hw->texture_update;
+   failover->pipe.resource_create = hw->resource_create;
+   failover->pipe.resource_destroy = hw->resource_destroy;
+   failover->pipe.create_surface = hw->create_surface;
+   failover->pipe.surface_destroy = hw->surface_destroy;
 #endif
 
    failover->pipe.flush = hw->flush;
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
index 50f6607..a572ad2 100644
--- a/src/gallium/drivers/galahad/glhd_context.c
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -662,17 +662,13 @@
 static void
 galahad_resource_copy_region(struct pipe_context *_pipe,
                               struct pipe_resource *_dst,
-                              struct pipe_subresource subdst,
+                              unsigned dst_level,
                               unsigned dstx,
                               unsigned dsty,
                               unsigned dstz,
                               struct pipe_resource *_src,
-                              struct pipe_subresource subsrc,
-                              unsigned srcx,
-                              unsigned srcy,
-                              unsigned srcz,
-                              unsigned width,
-                              unsigned height)
+                              unsigned src_level,
+                              const struct pipe_box *src_box)
 {
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
    struct galahad_resource *glhd_resource_dst = galahad_resource(_dst);
@@ -689,17 +685,13 @@
 
    pipe->resource_copy_region(pipe,
                               dst,
-                              subdst,
+                              dst_level,
                               dstx,
                               dsty,
                               dstz,
                               src,
-                              subsrc,
-                              srcx,
-                              srcy,
-                              srcz,
-                              width,
-                              height);
+                              src_level,
+                              src_box);
 }
 
 static void
@@ -781,8 +773,8 @@
 static unsigned int
 galahad_is_resource_referenced(struct pipe_context *_pipe,
                                 struct pipe_resource *_resource,
-                                unsigned face,
-                                unsigned level)
+                                unsigned level,
+                                int layer)
 {
    struct galahad_context *glhd_pipe = galahad_context(_pipe);
    struct galahad_resource *glhd_resource = galahad_resource(_resource);
@@ -791,8 +783,8 @@
 
    return pipe->is_resource_referenced(pipe,
                                        resource,
-                                       face,
-                                       level);
+                                       level,
+                                       layer);
 }
 
 static struct pipe_sampler_view *
@@ -823,10 +815,40 @@
                                  galahad_sampler_view(_view));
 }
 
+static struct pipe_surface *
+galahad_context_create_surface(struct pipe_context *_pipe,
+                                struct pipe_resource *_resource,
+                                const struct pipe_surface *templ)
+{
+   struct galahad_context *glhd_context = galahad_context(_pipe);
+   struct galahad_resource *glhd_resource = galahad_resource(_resource);
+   struct pipe_context *pipe = glhd_context->pipe;
+   struct pipe_resource *resource = glhd_resource->resource;
+   struct pipe_surface *result;
+
+   result = pipe->create_surface(pipe,
+                                 resource,
+                                 templ);
+
+   if (result)
+      return galahad_surface_create(glhd_context, glhd_resource, result);
+   return NULL;
+}
+
+static void
+galahad_context_surface_destroy(struct pipe_context *_pipe,
+                                struct pipe_surface *_surface)
+{
+   galahad_surface_destroy(galahad_context(_pipe),
+                           galahad_surface(_surface));
+}
+
+
+
 static struct pipe_transfer *
 galahad_context_get_transfer(struct pipe_context *_context,
                               struct pipe_resource *_resource,
-                              struct pipe_subresource sr,
+                              unsigned level,
                               unsigned usage,
                               const struct pipe_box *box)
 {
@@ -838,7 +860,7 @@
 
    result = context->get_transfer(context,
                                   resource,
-                                  sr,
+                                  level,
                                   usage,
                                   box);
 
@@ -915,7 +937,7 @@
 static void
 galahad_context_transfer_inline_write(struct pipe_context *_context,
                                        struct pipe_resource *_resource,
-                                       struct pipe_subresource sr,
+                                       unsigned level,
                                        unsigned usage,
                                        const struct pipe_box *box,
                                        const void *data,
@@ -929,7 +951,7 @@
 
    context->transfer_inline_write(context,
                                   resource,
-                                  sr,
+                                  level,
                                   usage,
                                   box,
                                   data,
@@ -1004,6 +1026,8 @@
    glhd_pipe->base.is_resource_referenced = galahad_is_resource_referenced;
    glhd_pipe->base.create_sampler_view = galahad_context_create_sampler_view;
    glhd_pipe->base.sampler_view_destroy = galahad_context_sampler_view_destroy;
+   glhd_pipe->base.create_surface = galahad_context_create_surface;
+   glhd_pipe->base.surface_destroy = galahad_context_surface_destroy;
    glhd_pipe->base.get_transfer = galahad_context_get_transfer;
    glhd_pipe->base.transfer_destroy = galahad_context_transfer_destroy;
    glhd_pipe->base.transfer_map = galahad_context_transfer_map;
diff --git a/src/gallium/drivers/galahad/glhd_objects.c b/src/gallium/drivers/galahad/glhd_objects.c
index 6c5a21a..b50d856 100644
--- a/src/gallium/drivers/galahad/glhd_objects.c
+++ b/src/gallium/drivers/galahad/glhd_objects.c
@@ -71,7 +71,8 @@
 
 
 struct pipe_surface *
-galahad_surface_create(struct galahad_resource *glhd_resource,
+galahad_surface_create(struct galahad_context *glhd_context,
+                        struct galahad_resource *glhd_resource,
                         struct pipe_surface *surface)
 {
    struct galahad_surface *glhd_surface;
@@ -100,10 +101,11 @@
 }
 
 void
-galahad_surface_destroy(struct galahad_surface *glhd_surface)
+galahad_surface_destroy(struct galahad_context *glhd_context,
+                         struct galahad_surface *glhd_surface)
 {
    pipe_resource_reference(&glhd_surface->base.texture, NULL);
-   pipe_surface_reference(&glhd_surface->surface, NULL);
+   glhd_context->pipe->surface_destroy(glhd_context->pipe, glhd_surface->surface);
    FREE(glhd_surface);
 }
 
diff --git a/src/gallium/drivers/galahad/glhd_objects.h b/src/gallium/drivers/galahad/glhd_objects.h
index dc74c5b..13dc748 100644
--- a/src/gallium/drivers/galahad/glhd_objects.h
+++ b/src/gallium/drivers/galahad/glhd_objects.h
@@ -149,11 +149,13 @@
 galahad_resource_destroy(struct galahad_resource *glhd_resource);
 
 struct pipe_surface *
-galahad_surface_create(struct galahad_resource *glhd_resource,
+galahad_surface_create(struct galahad_context *glhd_context,
+                       struct galahad_resource *glhd_resource,
                         struct pipe_surface *surface);
 
 void
-galahad_surface_destroy(struct galahad_surface *glhd_surface);
+galahad_surface_destroy(struct galahad_context *glhd_context,
+                         struct galahad_surface *glhd_surface);
 
 struct pipe_sampler_view *
 galahad_sampler_view_create(struct galahad_context *glhd_context,
diff --git a/src/gallium/drivers/galahad/glhd_screen.c b/src/gallium/drivers/galahad/glhd_screen.c
index b6cc41d..b4825be 100644
--- a/src/gallium/drivers/galahad/glhd_screen.c
+++ b/src/gallium/drivers/galahad/glhd_screen.c
@@ -223,39 +223,6 @@
    galahad_resource_destroy(galahad_resource(_resource));
 }
 
-static struct pipe_surface *
-galahad_screen_get_tex_surface(struct pipe_screen *_screen,
-                                struct pipe_resource *_resource,
-                                unsigned face,
-                                unsigned level,
-                                unsigned zslice,
-                                unsigned usage)
-{
-   struct galahad_screen *glhd_screen = galahad_screen(_screen);
-   struct galahad_resource *glhd_resource = galahad_resource(_resource);
-   struct pipe_screen *screen = glhd_screen->screen;
-   struct pipe_resource *resource = glhd_resource->resource;
-   struct pipe_surface *result;
-
-   result = screen->get_tex_surface(screen,
-                                    resource,
-                                    face,
-                                    level,
-                                    zslice,
-                                    usage);
-
-   if (result)
-      return galahad_surface_create(glhd_resource, result);
-   return NULL;
-}
-
-static void
-galahad_screen_tex_surface_destroy(struct pipe_surface *_surface)
-{
-   galahad_surface_destroy(galahad_surface(_surface));
-}
-
-
 
 static struct pipe_resource *
 galahad_screen_user_buffer_create(struct pipe_screen *_screen,
@@ -281,16 +248,18 @@
 
 static void
 galahad_screen_flush_frontbuffer(struct pipe_screen *_screen,
-                                  struct pipe_surface *_surface,
+                                  struct pipe_resource *_resource,
+                                  unsigned level, unsigned layer,
                                   void *context_private)
 {
    struct galahad_screen *glhd_screen = galahad_screen(_screen);
-   struct galahad_surface *glhd_surface = galahad_surface(_surface);
+   struct galahad_resource *glhd_resource = galahad_resource(_resource);
    struct pipe_screen *screen = glhd_screen->screen;
-   struct pipe_surface *surface = glhd_surface->surface;
+   struct pipe_resource *resource = glhd_resource->resource;
 
    screen->flush_frontbuffer(screen,
-                             surface,
+                             resource,
+                             level, layer,
                              context_private);
 }
 
@@ -360,8 +329,6 @@
    glhd_screen->base.resource_from_handle = galahad_screen_resource_from_handle;
    glhd_screen->base.resource_get_handle = galahad_screen_resource_get_handle;
    glhd_screen->base.resource_destroy = galahad_screen_resource_destroy;
-   glhd_screen->base.get_tex_surface = galahad_screen_get_tex_surface;
-   glhd_screen->base.tex_surface_destroy = galahad_screen_tex_surface_destroy;
    glhd_screen->base.user_buffer_create = galahad_screen_user_buffer_create;
    glhd_screen->base.flush_frontbuffer = galahad_screen_flush_frontbuffer;
    glhd_screen->base.fence_reference = galahad_screen_fence_reference;
diff --git a/src/gallium/drivers/i915/i915_resource.h b/src/gallium/drivers/i915/i915_resource.h
index 578c6bd..86620e6 100644
--- a/src/gallium/drivers/i915/i915_resource.h
+++ b/src/gallium/drivers/i915/i915_resource.h
@@ -78,7 +78,7 @@
 };
 
 unsigned i915_texture_offset(struct i915_texture *tex,
-	                     unsigned level, unsigned face);
+                             unsigned level, unsigned layer);
 void i915_init_screen_resource_functions(struct i915_screen *is);
 void i915_init_resource_functions(struct i915_context *i915);
 
diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c
index 0d37949..450203d 100644
--- a/src/gallium/drivers/i915/i915_resource_buffer.c
+++ b/src/gallium/drivers/i915/i915_resource_buffer.c
@@ -62,7 +62,7 @@
 
 static void *
 i915_buffer_transfer_map( struct pipe_context *pipe,
-			  struct pipe_transfer *transfer )
+                          struct pipe_transfer *transfer )
 {
    struct i915_buffer *buffer = i915_buffer(transfer->resource);
    return buffer->data + transfer->box.x;
@@ -71,19 +71,19 @@
 
 static void
 i915_buffer_transfer_inline_write( struct pipe_context *rm_ctx,
-				   struct pipe_resource *resource,
-				   struct pipe_subresource sr,
-				   unsigned usage,
-				   const struct pipe_box *box,
-				   const void *data,
-				   unsigned stride,
-				   unsigned slice_stride)
+                                   struct pipe_resource *resource,
+                                   unsigned level,
+                                   unsigned usage,
+                                   const struct pipe_box *box,
+                                   const void *data,
+                                   unsigned stride,
+                                   unsigned layer_stride)
 {
    struct i915_buffer *buffer = i915_buffer(resource);
 
    memcpy(buffer->data + box->x,
-	  data,
-	  box->width);
+          data,
+          box->width);
 }
 
 
@@ -115,7 +115,7 @@
    buf->b.vtbl = &i915_buffer_vtbl;
    pipe_reference_init(&buf->b.b.reference, 1);
    buf->b.b.screen = screen;
-   
+
    buf->data = MALLOC(template->width0);
    buf->free_on_destroy = TRUE;
 
@@ -135,7 +135,7 @@
 i915_user_buffer_create(struct pipe_screen *screen,
                         void *ptr,
                         unsigned bytes,
-			unsigned bind)
+                        unsigned bind)
 {
    struct i915_buffer *buf = CALLOC_STRUCT(i915_buffer);
 
@@ -152,6 +152,7 @@
    buf->b.b.width0 = bytes;
    buf->b.b.height0 = 1;
    buf->b.b.depth0 = 1;
+   buf->b.b.array_size = 1;
 
    buf->data = ptr;
    buf->free_on_destroy = FALSE;
diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c
index c80014b..f19106f 100644
--- a/src/gallium/drivers/i915/i915_resource_texture.c
+++ b/src/gallium/drivers/i915/i915_resource_texture.c
@@ -142,15 +142,15 @@
    tex->image_offset[level][0].nblocksy = 0;
 }
 
-inline unsigned i915_texture_offset(struct i915_texture *tex,
-			            unsigned level, unsigned face)
+INLINE unsigned i915_texture_offset(struct i915_texture *tex,
+                                    unsigned level, unsigned layer)
 {
-	unsigned x, y;
-	x = tex->image_offset[level][face].nblocksx
-               * util_format_get_blocksize(tex->b.b.format);
-	y = tex->image_offset[level][face].nblocksy;
+   unsigned x, y;
+   x = tex->image_offset[level][layer].nblocksx
+      * util_format_get_blocksize(tex->b.b.format);
+   y = tex->image_offset[level][layer].nblocksy;
 
-	return y * tex->stride + x;
+   return y * tex->stride + x;
 }
 
 static void
@@ -700,7 +700,7 @@
 
 static void
 i915_texture_destroy(struct pipe_screen *screen,
-		     struct pipe_resource *pt)
+                     struct pipe_resource *pt)
 {
    struct i915_texture *tex = i915_texture(pt);
    struct i915_winsys *iws = i915_screen(screen)->iws;
@@ -717,10 +717,10 @@
 
 static struct pipe_transfer * 
 i915_texture_get_transfer(struct pipe_context *context,
-			  struct pipe_resource *resource,
-			  struct pipe_subresource sr,
-			  unsigned usage,
-			  const struct pipe_box *box)
+                          struct pipe_resource *resource,
+                          unsigned level,
+                          unsigned usage,
+                          const struct pipe_box *box)
 {
    struct i915_texture *tex = i915_texture(resource);
    struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
@@ -728,36 +728,31 @@
       return NULL;
 
    transfer->resource = resource;
-   transfer->sr = sr;
+   transfer->level = level;
    transfer->usage = usage;
    transfer->box = *box;
    transfer->stride = tex->stride;
+   /* FIXME: layer_stride */
 
    return transfer;
 }
 
 static void *
 i915_texture_transfer_map(struct pipe_context *pipe,
-			  struct pipe_transfer *transfer)
+                          struct pipe_transfer *transfer)
 {
    struct pipe_resource *resource = transfer->resource;
    struct i915_texture *tex = i915_texture(resource);
    struct i915_winsys *iws = i915_screen(pipe->screen)->iws;
-   struct pipe_subresource sr = transfer->sr;
    struct pipe_box *box = &transfer->box;
    enum pipe_format format = resource->format;
    unsigned offset;
    char *map;
 
-   if (resource->target == PIPE_TEXTURE_CUBE) {
-      offset = i915_texture_offset(tex, sr.level, sr.face);
-   } else if (resource->target == PIPE_TEXTURE_3D) {
-      offset = i915_texture_offset(tex, sr.level, box->z);
-   } else {
-      offset = i915_texture_offset(tex, sr.level, 0);
-      assert(sr.face == 0);
+   if (resource->target != PIPE_TEXTURE_3D &&
+       resource->target != PIPE_TEXTURE_CUBE)
       assert(box->z == 0);
-   }
+   offset = i915_texture_offset(tex, transfer->level, box->z);
 
    map = iws->buffer_map(iws, tex->buffer,
                          (transfer->usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE);
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index a3c5113..f66478e 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -387,7 +387,6 @@
    is->base.fence_finish = i915_fence_finish;
 
    i915_init_screen_resource_functions(is);
-   i915_init_screen_surface_functions(is);
 
    i915_debug_init(is);
 
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 49d1fa6..c48d53f 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -237,7 +237,6 @@
 
       if (cbuf_surface) {
          struct i915_texture *tex = i915_texture(cbuf_surface->texture);
-         uint32_t tiling_bits = 0;
          assert(tex);
 
          OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
@@ -255,8 +254,10 @@
        */
       if (depth_surface) {
          struct i915_texture *tex = i915_texture(depth_surface->texture);
+         unsigned offset = i915_texture_offset(tex, depth_surface->u.tex.level,
+                                               depth_surface->u.tex.first_layer);
          assert(tex);
-         assert(depth_surface->offset == 0);
+         assert(offset == 0);
 
          OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 
@@ -412,18 +413,17 @@
       struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
       struct i915_texture *tex = i915_texture(cbuf_surface->texture);
       unsigned x, y;
-      int face;
+      int layer;
       uint32_t draw_offset;
       boolean ret;
 
       ret = framebuffer_size(&i915->framebuffer, &w, &h);
       assert(ret);
 
-      face = tex->b.b.target == PIPE_TEXTURE_CUBE ?
-               cbuf_surface->face : cbuf_surface->zslice;
+      layer = cbuf_surface->u.tex.first_layer;
 
-      x = tex->image_offset[cbuf_surface->level][face].nblocksx;
-      y = tex->image_offset[cbuf_surface->level][face].nblocksy;
+      x = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksx;
+      y = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksy;
 
       draw_offset = x | (y << 16);
 
diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c
index 8a09f93..becc6e9 100644
--- a/src/gallium/drivers/i915/i915_surface.c
+++ b/src/gallium/drivers/i915/i915_surface.c
@@ -43,11 +43,10 @@
  */
 static void
 i915_surface_copy(struct pipe_context *pipe,
-                  struct pipe_resource *dst, struct pipe_subresource subdst,
+                  struct pipe_resource *dst, unsigned dst_level,
                   unsigned dstx, unsigned dsty, unsigned dstz,
-                  struct pipe_resource *src, struct pipe_subresource subsrc,
-                  unsigned srcx, unsigned srcy, unsigned srcz,
-                  unsigned width, unsigned height)
+                  struct pipe_resource *src, unsigned src_level,
+                  const struct pipe_box *src_box)
 {
    struct i915_texture *dst_tex = i915_texture(dst);
    struct i915_texture *src_tex = i915_texture(src);
@@ -55,29 +54,17 @@
    struct pipe_resource *spt = &src_tex->b.b;
    unsigned dst_offset, src_offset;  /* in bytes */
 
-   if (dst->target == PIPE_TEXTURE_CUBE) {
-      dst_offset = i915_texture_offset(dst_tex, subdst.level, subdst.face);
-   }
-   else if (dst->target == PIPE_TEXTURE_3D) {
-      dst_offset = i915_texture_offset(dst_tex, subdst.level, dstz);
-   }
-   else {
-      dst_offset = i915_texture_offset(dst_tex, subdst.level, 0);
-      assert(subdst.face == 0);
+   /* XXX cannot copy 3d regions at this time */
+   assert(src_box->depth == 1);
+   if (dst->target != PIPE_TEXTURE_CUBE &&
+       dst->target != PIPE_TEXTURE_3D)
       assert(dstz == 0);
-   }
-   if (src->target == PIPE_TEXTURE_CUBE) {
-      src_offset = i915_texture_offset(src_tex, subsrc.level, subsrc.face);
-   }
-   else if (src->target == PIPE_TEXTURE_3D) {
-      src_offset = i915_texture_offset(src_tex, subsrc.level, srcz);
-   }
-   else {
-      src_offset = i915_texture_offset(src_tex, subsrc.level, 0);
-      assert(subsrc.face == 0);
-      assert(srcz == 0);
-   }
+   dst_offset = i915_texture_offset(dst_tex, dst_level, dstz);
 
+   if (src->target != PIPE_TEXTURE_CUBE &&
+       src->target != PIPE_TEXTURE_3D)
+      assert(src_box->z == 0);
+   src_offset = i915_texture_offset(src_tex, src_level, src_box->z);
 
    assert( dst != src );
    assert( util_format_get_blocksize(dpt->format) == util_format_get_blocksize(spt->format) );
@@ -90,7 +77,8 @@
                    util_format_get_blocksize(dpt->format),
                    (unsigned short) src_tex->stride, src_tex->buffer, src_offset,
                    (unsigned short) dst_tex->stride, dst_tex->buffer, dst_offset,
-                   (short) srcx, (short) srcy, (short) dstx, (short) dsty, (short) width, (short) height );
+                   (short) src_box->x, (short) src_box->y, (short) dstx, (short) dsty,
+                   (short) src_box->width, (short) src_box->height );
 }
 
 
@@ -104,6 +92,7 @@
    struct i915_texture *tex = i915_texture(dst->texture);
    struct pipe_resource *pt = &tex->b.b;
    union util_color uc;
+   unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
 
    assert(util_format_get_blockwidth(pt->format) == 1);
    assert(util_format_get_blockheight(pt->format) == 1);
@@ -113,7 +102,7 @@
                    util_format_get_blocksize(pt->format),
                    XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB,
                    (unsigned short) tex->stride,
-                   tex->buffer, dst->offset,
+                   tex->buffer, offset,
                    (short) dstx, (short) dsty,
                    (short) width, (short) height,
                    uc.ui );
@@ -132,6 +121,7 @@
    struct pipe_resource *pt = &tex->b.b;
    unsigned packedds;
    unsigned mask = 0;
+   unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer);
 
    assert(util_format_get_blockwidth(pt->format) == 1);
    assert(util_format_get_blockheight(pt->format) == 1);
@@ -151,7 +141,7 @@
                    util_format_get_blocksize(pt->format),
                    mask,
                    (unsigned short) tex->stride,
-                   tex->buffer, dst->offset,
+                   tex->buffer, offset,
                    (short) dstx, (short) dsty,
                    (short) width, (short) height,
                    packedds );
@@ -163,45 +153,37 @@
 
 
 static struct pipe_surface *
-i915_get_tex_surface(struct pipe_screen *screen,
-                     struct pipe_resource *pt,
-                     unsigned face, unsigned level, unsigned zslice,
-                     unsigned flags)
+i915_create_surface(struct pipe_context *ctx,
+                    struct pipe_resource *pt,
+                    const struct pipe_surface *surf_tmpl)
 {
-   struct i915_texture *tex = i915_texture(pt);
    struct pipe_surface *ps;
-   unsigned offset;  /* in bytes */
 
-   if (pt->target == PIPE_TEXTURE_CUBE) {
-      offset = i915_texture_offset(tex, level, face);
-   }
-   else if (pt->target == PIPE_TEXTURE_3D) {
-      offset = i915_texture_offset(tex, level, zslice);
-   }
-   else {
-      offset = i915_texture_offset(tex, level, 0);
-      assert(face == 0);
-      assert(zslice == 0);
-   }
+   assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
+   if (pt->target != PIPE_TEXTURE_CUBE &&
+       pt->target != PIPE_TEXTURE_3D)
+      assert(surf_tmpl->u.tex.first_layer == 0);
 
    ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
+      /* could subclass pipe_surface and store offset as it used to do */
       pipe_reference_init(&ps->reference, 1);
       pipe_resource_reference(&ps->texture, pt);
-      ps->format = pt->format;
-      ps->width = u_minify(pt->width0, level);
-      ps->height = u_minify(pt->height0, level);
-      ps->offset = offset;
-      ps->usage = flags;
-      ps->zslice = zslice;
-      ps->level = level;
-      ps->face = face;
+      ps->format = surf_tmpl->format;
+      ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
+      ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
+      ps->u.tex.level = surf_tmpl->u.tex.level;
+      ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+      ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
+      ps->usage = surf_tmpl->usage;
+      ps->context = ctx;
    }
    return ps;
 }
 
 static void
-i915_tex_surface_destroy(struct pipe_surface *surf)
+i915_surface_destroy(struct pipe_context *ctx,
+                     struct pipe_surface *surf)
 {
    pipe_resource_reference(&surf->texture, NULL);
    FREE(surf);
@@ -214,13 +196,6 @@
    i915->base.resource_copy_region = i915_surface_copy;
    i915->base.clear_render_target = i915_clear_render_target;
    i915->base.clear_depth_stencil = i915_clear_depth_stencil;
-}
-
-/* No good reason for these to be in the screen.
- */
-void
-i915_init_screen_surface_functions(struct i915_screen *is)
-{
-   is->base.get_tex_surface = i915_get_tex_surface;
-   is->base.tex_surface_destroy = i915_tex_surface_destroy;
+   i915->base.create_surface = i915_create_surface;
+   i915->base.surface_destroy = i915_surface_destroy;
 }
diff --git a/src/gallium/drivers/i915/i915_surface.h b/src/gallium/drivers/i915/i915_surface.h
index 448106d..70b61de 100644
--- a/src/gallium/drivers/i915/i915_surface.h
+++ b/src/gallium/drivers/i915/i915_surface.h
@@ -32,7 +32,6 @@
 struct i915_screen;
 
 void i915_init_surface_functions( struct i915_context *i915 );
-void i915_init_screen_surface_functions( struct i915_screen *is );
 
 
 #endif /* I915_SCREEN_H */
diff --git a/src/gallium/drivers/i965/Makefile b/src/gallium/drivers/i965/Makefile
index b0b0970..a0331f8 100644
--- a/src/gallium/drivers/i965/Makefile
+++ b/src/gallium/drivers/i965/Makefile
@@ -33,6 +33,7 @@
 	brw_pipe_flush.c \
 	brw_pipe_misc.c \
 	brw_pipe_sampler.c \
+        brw_pipe_surface.c \
 	brw_pipe_vertex.c \
 	brw_pipe_clear.c \
 	brw_pipe_rast.c \
@@ -66,7 +67,6 @@
 	brw_resource_buffer.c \
 	brw_resource_texture.c \
 	brw_resource_texture_layout.c \
-	brw_screen_surface.c \
 	brw_batchbuffer.c \
 	brw_winsys_debug.c \
 	intel_decode.c
diff --git a/src/gallium/drivers/i965/SConscript b/src/gallium/drivers/i965/SConscript
index 019af68..3ef6c88 100644
--- a/src/gallium/drivers/i965/SConscript
+++ b/src/gallium/drivers/i965/SConscript
@@ -36,6 +36,8 @@
 		'brw_pipe_query.c',
 		'brw_pipe_rast.c',
 		'brw_pipe_sampler.c',
+                'brw_pipe_surface.c',
+                'brw_pipe_surface.c',
 		'brw_pipe_shader.c',
 		'brw_pipe_vertex.c',
 		'brw_resource.c',
@@ -43,7 +45,6 @@
 		'brw_resource_texture.c',
 		'brw_resource_texture_layout.c',
 		'brw_screen.c',
-		'brw_screen_surface.c',
 		'brw_structs_dump.c',
 		'brw_sf.c',
 		'brw_sf_emit.c',
diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c
index 227bc79..a2736f7 100644
--- a/src/gallium/drivers/i965/brw_context.c
+++ b/src/gallium/drivers/i965/brw_context.c
@@ -131,6 +131,7 @@
    brw_pipe_shader_init( brw );
    brw_pipe_vertex_init( brw );
    brw_pipe_clear_init( brw );
+   brw_pipe_surface_init( brw );
 
    brw_hw_cc_init( brw );
 
diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h
index 56d351f..d927f38 100644
--- a/src/gallium/drivers/i965/brw_context.h
+++ b/src/gallium/drivers/i965/brw_context.h
@@ -821,6 +821,7 @@
 void brw_pipe_shader_cleanup( struct brw_context *brw );
 void brw_pipe_vertex_cleanup( struct brw_context *brw );
 void brw_pipe_clear_cleanup( struct brw_context *brw );
+void brw_pipe_surface_init( struct brw_context *brw );
 
 void brw_hw_cc_init( struct brw_context *brw );
 void brw_hw_cc_cleanup( struct brw_context *brw );
diff --git a/src/gallium/drivers/i965/brw_misc_state.c b/src/gallium/drivers/i965/brw_misc_state.c
index b5029ce..6d89b5d 100644
--- a/src/gallium/drivers/i965/brw_misc_state.c
+++ b/src/gallium/drivers/i965/brw_misc_state.c
@@ -287,11 +287,12 @@
       OUT_BATCH(((pitch * cpp) - 1) |
 		(format << 18) |
 		(BRW_TILEWALK_YMAJOR << 26) |
-		((surface->layout != PIPE_SURFACE_LAYOUT_LINEAR) << 27) |
+                /* always linear ?
+		((surface->layout != PIPE_SURFACE_LAYOUT_LINEAR) << 27) |*/
 		(BRW_SURFACE_2D << 29));
       OUT_RELOC(bo,
 		BRW_USAGE_DEPTH_BUFFER,
-		surface->offset);
+		brw_surface(surface)->offset);
       OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) |
 		((pitch - 1) << 6) |
 		((surface->height - 1) << 19));
diff --git a/src/gallium/drivers/i965/brw_pipe_clear.c b/src/gallium/drivers/i965/brw_pipe_clear.c
index d5cff33..7bf3ea6 100644
--- a/src/gallium/drivers/i965/brw_pipe_clear.c
+++ b/src/gallium/drivers/i965/brw_pipe_clear.c
@@ -64,7 +64,7 @@
    debug_printf("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
                 __FUNCTION__,
                 (void *)surface->bo, pitch * cpp,
-                surface->base.offset,
+                surface->offset,
                 x1, y1, x2 - x1, y2 - y1);
 
    BR13 = 0xf0 << 16;
@@ -99,7 +99,7 @@
    OUT_BATCH((y2 << 16) | x2);
    OUT_RELOC(surface->bo,
              BRW_USAGE_BLIT_DEST,
-             surface->base.offset);
+             surface->offset);
    OUT_BATCH(value);
    ADVANCE_BATCH();
 
diff --git a/src/gallium/drivers/i965/brw_screen_surface.c b/src/gallium/drivers/i965/brw_pipe_surface.c
similarity index 77%
rename from src/gallium/drivers/i965/brw_screen_surface.c
rename to src/gallium/drivers/i965/brw_pipe_surface.c
index f288fdb..4deead9 100644
--- a/src/gallium/drivers/i965/brw_screen_surface.c
+++ b/src/gallium/drivers/i965/brw_pipe_surface.c
@@ -35,6 +35,7 @@
 
 #include "pipe/p_screen.h"
 #include "brw_screen.h"
+#include "brw_context.h"
 #include "brw_defines.h"
 #include "brw_resource.h"
 #include "brw_winsys.h"
@@ -108,9 +109,10 @@
  * where it would be illegal (perhaps due to tiling constraints) to do
  * this in-place.
  * 
- * Currently not implmented, not sure if it's needed.
+ * Currently not implemented, not sure if it's needed.
  */
 static struct brw_surface *create_linear_view( struct brw_screen *brw_screen,
+                                               struct pipe_context *pipe,
 					       struct brw_texture *tex,
 					       union brw_surface_id id,
 					       unsigned usage )
@@ -123,9 +125,10 @@
  * texture's storage.
  */
 static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen,
-						  struct brw_texture *tex,
-						  union brw_surface_id id,
-						  unsigned usage )
+                                                 struct pipe_context *pipe,
+                                                 struct brw_texture *tex,
+                                                 union brw_surface_id id,
+                                                 unsigned usage )
 {
    struct brw_surface *surface;
 
@@ -137,17 +140,18 @@
 
    /* XXX: ignoring render-to-slice-of-3d-texture
     */
-   assert(id.bits.zslice == 0);
+   assert(tex->b.b.target != PIPE_TEXTURE_3D || id.bits.layer == 0);
 
+   surface->base.context = pipe;
    surface->base.format = tex->b.b.format;
    surface->base.width = u_minify(tex->b.b.width0, id.bits.level);
    surface->base.height = u_minify(tex->b.b.height0, id.bits.level);
-   surface->base.offset = tex->image_offset[id.bits.level][id.bits.face];
    surface->base.usage = usage;
-   surface->base.zslice = id.bits.zslice;
-   surface->base.face = id.bits.face;
-   surface->base.level = id.bits.level;
+   surface->base.u.tex.first_layer = id.bits.layer;
+   surface->base.u.tex.last_layer = surface->base.u.tex.first_layer;
+   surface->base.u.tex.level = id.bits.level;
    surface->id = id;
+   surface->offset = tex->image_offset[id.bits.level][id.bits.layer];
    surface->cpp = tex->cpp;
    surface->pitch = tex->pitch;
    surface->tiling = tex->tiling;
@@ -159,11 +163,11 @@
    surface->ss.ss0.surface_type = BRW_SURFACE_2D;
 
    if (tex->tiling == BRW_TILING_NONE) {
-      surface->ss.ss1.base_addr = surface->base.offset;
+      surface->ss.ss1.base_addr = surface->offset;
    } else {
-      uint32_t tile_offset = surface->base.offset % 4096;
+      uint32_t tile_offset = surface->offset % 4096;
 
-      surface->ss.ss1.base_addr = surface->base.offset - tile_offset;
+      surface->ss.ss1.base_addr = surface->offset - tile_offset;
 
       if (brw_screen->chipset.is_g4x) {
 	 if (tex->tiling == BRW_TILING_X) {
@@ -198,23 +202,21 @@
 
 /* Get a surface which is view into a texture 
  */
-static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen,
-						struct pipe_resource *pt,
-						unsigned face, unsigned level,
-						unsigned zslice,
-						unsigned usage )
+static struct pipe_surface *brw_create_surface(struct pipe_context *pipe,
+                                               struct pipe_resource *pt,
+                                               const struct pipe_surface *surf_tmpl)
 {
    struct brw_texture *tex = brw_texture(pt);
-   struct brw_screen *bscreen = brw_screen(screen);
+   struct brw_screen *bscreen = brw_screen(pipe->screen);
    struct brw_surface *surface;
    union brw_surface_id id;
    int type;
 
-   id.bits.face = face;
-   id.bits.level = level;
-   id.bits.zslice = zslice;
+   assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
+   id.bits.level = surf_tmpl->u.tex.level;
+   id.bits.layer = surf_tmpl->u.tex.first_layer;
 
-   if (need_linear_view(bscreen, tex, id, usage)) 
+   if (need_linear_view(bscreen, tex, id, surf_tmpl->usage))
       type = BRW_VIEW_LINEAR;
    else
       type = BRW_VIEW_IN_PLACE;
@@ -227,10 +229,10 @@
 
    switch (type) {
    case BRW_VIEW_LINEAR:
-      surface = create_linear_view( bscreen, tex, id, usage );
+      surface = create_linear_view( bscreen, pipe, tex, id, surf_tmpl->usage );
       break;
    case BRW_VIEW_IN_PLACE:
-      surface = create_in_place_view( bscreen, tex, id, usage );
+      surface = create_in_place_view( bscreen, pipe, tex, id, surf_tmpl->usage );
       break;
    }
 
@@ -239,7 +241,8 @@
 }
 
 
-static void brw_tex_surface_destroy( struct pipe_surface *surf )
+static void brw_surface_destroy( struct pipe_context *pipe,
+                                 struct pipe_surface *surf )
 {
    struct brw_surface *surface = brw_surface(surf);
 
@@ -249,13 +252,12 @@
    bo_reference(&surface->bo, NULL);
    pipe_resource_reference( &surface->base.texture, NULL );
 
-
    FREE(surface);
 }
 
 
-void brw_screen_tex_surface_init( struct brw_screen *brw_screen )
+void brw_pipe_surface_init( struct brw_context *brw )
 {
-   brw_screen->base.get_tex_surface = brw_get_tex_surface;
-   brw_screen->base.tex_surface_destroy = brw_tex_surface_destroy;
+   brw->base.create_surface = brw_create_surface;
+   brw->base.surface_destroy = brw_surface_destroy;
 }
diff --git a/src/gallium/drivers/i965/brw_resource_buffer.c b/src/gallium/drivers/i965/brw_resource_buffer.c
index 5f9e8a8..afb96ee 100644
--- a/src/gallium/drivers/i965/brw_resource_buffer.c
+++ b/src/gallium/drivers/i965/brw_resource_buffer.c
@@ -92,9 +92,9 @@
 
 
 static unsigned brw_buffer_is_referenced( struct pipe_context *pipe,
-					 struct pipe_resource *resource,
-					 unsigned face,
-					 unsigned level)
+                                          struct pipe_resource *resource,
+                                          unsigned level,
+                                          int layer)
 {
    struct brw_context *brw = brw_context(pipe);
    struct brw_winsys_buffer *batch_bo = brw->batch->buf;
@@ -194,6 +194,7 @@
    buf->b.b.width0 = bytes;
    buf->b.b.height0 = 1;
    buf->b.b.depth0 = 1;
+   buf->b.b.array_size = 1;
 
    buf->user_buffer = ptr;
    
diff --git a/src/gallium/drivers/i965/brw_resource_texture.c b/src/gallium/drivers/i965/brw_resource_texture.c
index 3860d18..fded2da 100644
--- a/src/gallium/drivers/i965/brw_resource_texture.c
+++ b/src/gallium/drivers/i965/brw_resource_texture.c
@@ -229,8 +229,8 @@
 
 static unsigned brw_texture_is_referenced( struct pipe_context *pipe,
 					   struct pipe_resource *texture,
-					   unsigned face, 
-					   unsigned level )
+					   unsigned level,
+					   int layer )
 {
    struct brw_context *brw = brw_context(pipe);
    struct brw_screen *bscreen = brw_screen(pipe->screen);
@@ -246,7 +246,7 @@
    if (bscreen->sws->bo_references( batch_bo, tex->bo ))
       return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
 
-   /* Find any view on this texture for this face/level and see if it
+   /* Find any view on this texture for this level/layer and see if it
     * is referenced:
     */
    for (i = 0; i < 2; i++) {
@@ -254,7 +254,7 @@
          if (surf->bo == tex->bo)
             continue;
 
-         if (surf->id.bits.face != face ||
+         if (!(layer == -1 || surf->id.bits.layer == layer) ||
              surf->id.bits.level != level)
             continue;
          
@@ -274,10 +274,10 @@
 
 static struct pipe_transfer * 
 brw_texture_get_transfer(struct pipe_context *context,
-			  struct pipe_resource *resource,
-			  struct pipe_subresource sr,
-			  unsigned usage,
-			  const struct pipe_box *box)
+                         struct pipe_resource *resource,
+                         unsigned level,
+                         unsigned usage,
+                         const struct pipe_box *box)
 {
    struct brw_texture *tex = brw_texture(resource);
    struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
@@ -285,10 +285,11 @@
       return NULL;
 
    transfer->resource = resource;
-   transfer->sr = sr;
+   transfer->level = level;
    transfer->usage = usage;
    transfer->box = *box;
    transfer->stride = tex->pitch * tex->cpp;
+   /* FIXME: layer_stride */
 
    return transfer;
 }
@@ -301,24 +302,16 @@
    struct pipe_resource *resource = transfer->resource;
    struct brw_texture *tex = brw_texture(transfer->resource);
    struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws;
-   struct pipe_subresource sr = transfer->sr;
    struct pipe_box *box = &transfer->box;
    enum pipe_format format = resource->format;
    unsigned usage = transfer->usage;
    unsigned offset;
    char *map;
 
-   if (resource->target == PIPE_TEXTURE_CUBE) {
-      offset = tex->image_offset[sr.level][sr.face];
-   }
-   else if (resource->target == PIPE_TEXTURE_3D) {
-      offset = tex->image_offset[sr.level][box->z];
-   }
-   else {
-      offset = tex->image_offset[sr.level][0];
-      assert(sr.face == 0);
+   if (resource->target != PIPE_TEXTURE_3D &&
+       resource->target != PIPE_TEXTURE_CUBE)
       assert(box->z == 0);
-   }
+   offset = tex->image_offset[transfer->level][box->z];
 
    map = sws->bo_map(tex->bo, 
                      BRW_DATA_OTHER,
diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c
index 29486f5..f5b75b1 100644
--- a/src/gallium/drivers/i965/brw_screen.c
+++ b/src/gallium/drivers/i965/brw_screen.c
@@ -470,7 +470,6 @@
    bscreen->base.fence_finish = brw_fence_finish;
 
    brw_init_screen_resource_functions(bscreen);
-   brw_screen_tex_surface_init(bscreen);
 
    bscreen->no_tiling = debug_get_option("BRW_NO_TILING", FALSE) != NULL;
    
diff --git a/src/gallium/drivers/i965/brw_screen.h b/src/gallium/drivers/i965/brw_screen.h
index 522a3bf..58e293b 100644
--- a/src/gallium/drivers/i965/brw_screen.h
+++ b/src/gallium/drivers/i965/brw_screen.h
@@ -52,9 +52,8 @@
 
 union brw_surface_id {
    struct {
-      unsigned face:3;
-      unsigned zslice:13;
       unsigned level:16;
+      unsigned layer:16;
    } bits;
    unsigned value;
 };
@@ -63,8 +62,9 @@
 struct brw_surface
 {
    struct pipe_surface base;
-   
+
    union brw_surface_id id;
+   unsigned offset;
    unsigned cpp;
    unsigned pitch;
    unsigned draw_offset;
@@ -96,7 +96,5 @@
 unsigned
 brw_surface_pitch( const struct pipe_surface *surface );
 
-void brw_screen_tex_surface_init( struct brw_screen *brw_screen );
-
 
 #endif /* BRW_SCREEN_H */
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index de83c24..3efbd6a 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -577,17 +577,13 @@
 static void
 identity_resource_copy_region(struct pipe_context *_pipe,
                               struct pipe_resource *_dst,
-                              struct pipe_subresource subdst,
+                              unsigned dst_level,
                               unsigned dstx,
                               unsigned dsty,
                               unsigned dstz,
                               struct pipe_resource *_src,
-                              struct pipe_subresource subsrc,
-                              unsigned srcx,
-                              unsigned srcy,
-                              unsigned srcz,
-                              unsigned width,
-                              unsigned height)
+                              unsigned src_level,
+                              const struct pipe_box *src_box)
 {
    struct identity_context *id_pipe = identity_context(_pipe);
    struct identity_resource *id_resource_dst = identity_resource(_dst);
@@ -598,17 +594,13 @@
 
    pipe->resource_copy_region(pipe,
                               dst,
-                              subdst,
+                              dst_level,
                               dstx,
                               dsty,
                               dstz,
                               src,
-                              subsrc,
-                              srcx,
-                              srcy,
-                              srcz,
-                              width,
-                              height);
+                              src_level,
+                              src_box);
 }
 
 static void
@@ -690,8 +682,8 @@
 static unsigned int
 identity_is_resource_referenced(struct pipe_context *_pipe,
                                 struct pipe_resource *_resource,
-                                unsigned face,
-                                unsigned level)
+                                unsigned level,
+                                int layer)
 {
    struct identity_context *id_pipe = identity_context(_pipe);
    struct identity_resource *id_resource = identity_resource(_resource);
@@ -700,8 +692,8 @@
 
    return pipe->is_resource_referenced(pipe,
                                        resource,
-                                       face,
-                                       level);
+                                       level,
+                                       layer);
 }
 
 static struct pipe_sampler_view *
@@ -732,10 +724,38 @@
                                  identity_sampler_view(_view));
 }
 
+static struct pipe_surface *
+identity_context_create_surface(struct pipe_context *_pipe,
+                                struct pipe_resource *_resource,
+                                const struct pipe_surface *templ)
+{
+   struct identity_context *id_context = identity_context(_pipe);
+   struct identity_resource *id_resource = identity_resource(_resource);
+   struct pipe_context *pipe = id_context->pipe;
+   struct pipe_resource *resource = id_resource->resource;
+   struct pipe_surface *result;
+
+   result = pipe->create_surface(pipe,
+                                 resource,
+                                 templ);
+
+   if (result)
+      return identity_surface_create(id_context, id_resource, result);
+   return NULL;
+}
+
+static void
+identity_context_surface_destroy(struct pipe_context *_pipe,
+                                 struct pipe_surface *_surf)
+{
+   identity_surface_destroy(identity_context(_pipe),
+                            identity_surface(_surf));
+}
+
 static struct pipe_transfer *
 identity_context_get_transfer(struct pipe_context *_context,
                               struct pipe_resource *_resource,
-                              struct pipe_subresource sr,
+                              unsigned level,
                               unsigned usage,
                               const struct pipe_box *box)
 {
@@ -747,7 +767,7 @@
 
    result = context->get_transfer(context,
                                   resource,
-                                  sr,
+                                  level,
                                   usage,
                                   box);
 
@@ -812,12 +832,12 @@
 static void 
 identity_context_transfer_inline_write(struct pipe_context *_context,
                                        struct pipe_resource *_resource,
-                                       struct pipe_subresource sr,
+                                       unsigned level,
                                        unsigned usage,
                                        const struct pipe_box *box,
                                        const void *data,
                                        unsigned stride,
-                                       unsigned slice_stride)
+                                       unsigned layer_stride)
 {
    struct identity_context *id_context = identity_context(_context);
    struct identity_resource *id_resource = identity_resource(_resource);
@@ -826,12 +846,12 @@
 
    context->transfer_inline_write(context,
                                   resource,
-                                  sr,
+                                  level,
                                   usage,
                                   box,
                                   data,
                                   stride,
-                                  slice_stride);
+                                  layer_stride);
 }
 
 
@@ -899,6 +919,8 @@
    id_pipe->base.clear_depth_stencil = identity_clear_depth_stencil;
    id_pipe->base.flush = identity_flush;
    id_pipe->base.is_resource_referenced = identity_is_resource_referenced;
+   id_pipe->base.create_surface = identity_context_create_surface;
+   id_pipe->base.surface_destroy = identity_context_surface_destroy;
    id_pipe->base.create_sampler_view = identity_context_create_sampler_view;
    id_pipe->base.sampler_view_destroy = identity_context_sampler_view_destroy;
    id_pipe->base.get_transfer = identity_context_get_transfer;
diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c
index 593928f..6345441 100644
--- a/src/gallium/drivers/identity/id_objects.c
+++ b/src/gallium/drivers/identity/id_objects.c
@@ -71,7 +71,8 @@
 
 
 struct pipe_surface *
-identity_surface_create(struct identity_resource *id_resource,
+identity_surface_create(struct identity_context *id_context,
+                        struct identity_resource *id_resource,
                         struct pipe_surface *surface)
 {
    struct identity_surface *id_surface;
@@ -100,10 +101,12 @@
 }
 
 void
-identity_surface_destroy(struct identity_surface *id_surface)
+identity_surface_destroy(struct identity_context *id_context,
+                         struct identity_surface *id_surface)
 {
    pipe_resource_reference(&id_surface->base.texture, NULL);
-   pipe_surface_reference(&id_surface->surface, NULL);
+   id_context->pipe->surface_destroy(id_context->pipe,
+                                     id_surface->surface);
    FREE(id_surface);
 }
 
diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h
index e8deabf..181f2d6 100644
--- a/src/gallium/drivers/identity/id_objects.h
+++ b/src/gallium/drivers/identity/id_objects.h
@@ -147,11 +147,13 @@
 identity_resource_destroy(struct identity_resource *id_resource);
 
 struct pipe_surface *
-identity_surface_create(struct identity_resource *id_resource,
+identity_surface_create(struct identity_context *id_context,
+                        struct identity_resource *id_resource,
                         struct pipe_surface *surface);
 
 void
-identity_surface_destroy(struct identity_surface *id_surface);
+identity_surface_destroy(struct identity_context *id_context,
+                         struct identity_surface *id_surface);
 
 struct pipe_sampler_view *
 identity_sampler_view_create(struct identity_context *id_context,
diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c
index 5fb464b..644481b 100644
--- a/src/gallium/drivers/identity/id_screen.c
+++ b/src/gallium/drivers/identity/id_screen.c
@@ -189,39 +189,6 @@
    identity_resource_destroy(identity_resource(_resource));
 }
 
-static struct pipe_surface *
-identity_screen_get_tex_surface(struct pipe_screen *_screen,
-                                struct pipe_resource *_resource,
-                                unsigned face,
-                                unsigned level,
-                                unsigned zslice,
-                                unsigned usage)
-{
-   struct identity_screen *id_screen = identity_screen(_screen);
-   struct identity_resource *id_resource = identity_resource(_resource);
-   struct pipe_screen *screen = id_screen->screen;
-   struct pipe_resource *resource = id_resource->resource;
-   struct pipe_surface *result;
-
-   result = screen->get_tex_surface(screen,
-                                    resource,
-                                    face,
-                                    level,
-                                    zslice,
-                                    usage);
-
-   if (result)
-      return identity_surface_create(id_resource, result);
-   return NULL;
-}
-
-static void
-identity_screen_tex_surface_destroy(struct pipe_surface *_surface)
-{
-   identity_surface_destroy(identity_surface(_surface));
-}
-
-
 
 static struct pipe_resource *
 identity_screen_user_buffer_create(struct pipe_screen *_screen,
@@ -247,16 +214,18 @@
 
 static void
 identity_screen_flush_frontbuffer(struct pipe_screen *_screen,
-                                  struct pipe_surface *_surface,
+                                  struct pipe_resource *_resource,
+                                  unsigned level, unsigned layer,
                                   void *context_private)
 {
    struct identity_screen *id_screen = identity_screen(_screen);
-   struct identity_surface *id_surface = identity_surface(_surface);
+   struct identity_resource *id_resource = identity_resource(_resource);
    struct pipe_screen *screen = id_screen->screen;
-   struct pipe_surface *surface = id_surface->surface;
+   struct pipe_resource *resource = id_resource->resource;
 
    screen->flush_frontbuffer(screen,
-                             surface,
+                             resource,
+                             level, layer,
                              context_private);
 }
 
@@ -323,8 +292,6 @@
    id_screen->base.resource_from_handle = identity_screen_resource_from_handle;
    id_screen->base.resource_get_handle = identity_screen_resource_get_handle;
    id_screen->base.resource_destroy = identity_screen_resource_destroy;
-   id_screen->base.get_tex_surface = identity_screen_get_tex_surface;
-   id_screen->base.tex_surface_destroy = identity_screen_tex_surface_destroy;
    id_screen->base.user_buffer_create = identity_screen_user_buffer_create;
    id_screen->base.flush_frontbuffer = identity_screen_flush_frontbuffer;
    id_screen->base.fence_reference = identity_screen_fence_reference;
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
index e8d00cf..85e3cde 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.c
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -108,8 +108,8 @@
 boolean
 llvmpipe_flush_resource(struct pipe_context *pipe,
                         struct pipe_resource *resource,
-                        unsigned face,
                         unsigned level,
+                        int layer,
                         unsigned flush_flags,
                         boolean read_only,
                         boolean cpu_access,
@@ -118,7 +118,7 @@
 {
    unsigned referenced;
 
-   referenced = pipe->is_resource_referenced(pipe, resource, face, level);
+   referenced = pipe->is_resource_referenced(pipe, resource, level, layer);
 
    if ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
        ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) {
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.h b/src/gallium/drivers/llvmpipe/lp_flush.h
index 3626ce4..579d24c 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.h
+++ b/src/gallium/drivers/llvmpipe/lp_flush.h
@@ -47,8 +47,8 @@
 boolean
 llvmpipe_flush_resource(struct pipe_context *pipe,
                         struct pipe_resource *resource,
-                        unsigned face,
                         unsigned level,
+                        int layer,
                         unsigned flush_flags,
                         boolean read_only,
                         boolean cpu_access,
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index dd6e6d5..dafadc1 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -120,8 +120,8 @@
           * and update the tile's layout info.
           */
          (void) llvmpipe_get_texture_tile(lpt,
-                                          zsbuf->face + zsbuf->zslice,
-                                          zsbuf->level,
+                                          zsbuf->u.tex.first_layer,
+                                          zsbuf->u.tex.level,
                                           usage,
                                           task->x,
                                           task->y);
@@ -289,7 +289,6 @@
 
 
 
-
 /**
  * Convert the color tile from tiled to linear layout.
  * This is generally only done when we're flushing the scene just prior to
@@ -307,15 +306,15 @@
 
    for (buf = 0; buf < scene->fb.nr_cbufs; buf++) {
       struct pipe_surface *cbuf = scene->fb.cbufs[buf];
-      const unsigned face_slice = cbuf->face + cbuf->zslice;
-      const unsigned level = cbuf->level;
+      const unsigned layer = cbuf->u.tex.first_layer;
+      const unsigned level = cbuf->u.tex.level;
       struct llvmpipe_resource *lpt = llvmpipe_resource(cbuf->texture);
 
       if (!task->color_tiles[buf])
          continue;
 
       llvmpipe_unswizzle_cbuf_tile(lpt,
-                                   face_slice,
+                                   layer,
                                    level,
                                    task->x, task->y,
                                    task->color_tiles[buf]);
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 6864aee..cd686bc 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -194,8 +194,8 @@
 
       if (usage != LP_TEX_USAGE_WRITE_ALL) {
          llvmpipe_swizzle_cbuf_tile(lpt,
-                                    cbuf->face + cbuf->zslice,
-                                    cbuf->level,
+                                    cbuf->u.tex.first_layer,
+                                    cbuf->u.tex.level,
                                     task->x, task->y,
                                     task->color_tiles[buf]);
       }
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index a4fdf7c..978d17c 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -136,30 +136,30 @@
    int i;
 
    //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
-   
+
    for (i = 0; i < scene->fb.nr_cbufs; i++) {
       struct pipe_surface *cbuf = scene->fb.cbufs[i];
+      assert(cbuf->u.tex.first_layer == cbuf->u.tex.last_layer);
       scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
-                                                        cbuf->level);
+                                                        cbuf->u.tex.level);
 
       scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
-                                                  cbuf->face,
-                                                  cbuf->level,
-                                                  cbuf->zslice,
+                                                  cbuf->u.tex.level,
+                                                  cbuf->u.tex.first_layer,
                                                   LP_TEX_USAGE_READ_WRITE,
                                                   LP_TEX_LAYOUT_LINEAR);
    }
 
    if (fb->zsbuf) {
       struct pipe_surface *zsbuf = scene->fb.zsbuf;
-      scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->level);
+      assert(zsbuf->u.tex.first_layer == zsbuf->u.tex.last_layer);
+      scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->u.tex.level);
       scene->zsbuf.blocksize = 
          util_format_get_blocksize(zsbuf->texture->format);
 
       scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture,
-                                               zsbuf->face,
-                                               zsbuf->level,
-                                               zsbuf->zslice,
+                                               zsbuf->u.tex.level,
+                                               zsbuf->u.tex.first_layer,
                                                LP_TEX_USAGE_READ_WRITE,
                                                LP_TEX_LAYOUT_NONE);
    }
@@ -181,9 +181,8 @@
       if (scene->cbufs[i].map) {
          struct pipe_surface *cbuf = scene->fb.cbufs[i];
          llvmpipe_resource_unmap(cbuf->texture,
-                                 cbuf->face,
-                                 cbuf->level,
-                                 cbuf->zslice);
+                                 cbuf->u.tex.level,
+                                 cbuf->u.tex.first_layer);
          scene->cbufs[i].map = NULL;
       }
    }
@@ -192,9 +191,8 @@
    if (scene->zsbuf.map) {
       struct pipe_surface *zsbuf = scene->fb.zsbuf;
       llvmpipe_resource_unmap(zsbuf->texture,
-                             zsbuf->face,
-                             zsbuf->level,
-                             zsbuf->zslice);
+                              zsbuf->u.tex.level,
+                              zsbuf->u.tex.first_layer);
       scene->zsbuf.map = NULL;
    }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index ad0ea75..9459a3c 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -287,12 +287,13 @@
 
 static void
 llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
-                           struct pipe_surface *surface,
+                           struct pipe_resource *resource,
+                           unsigned level, unsigned layer,
                            void *context_private)
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
-   struct llvmpipe_resource *texture = llvmpipe_resource(surface->texture);
+   struct llvmpipe_resource *texture = llvmpipe_resource(resource);
 
    assert(texture->dt);
    if (texture->dt)
diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c
index 164242e..e7e46a6 100644
--- a/src/gallium/drivers/llvmpipe/lp_surface.c
+++ b/src/gallium/drivers/llvmpipe/lp_surface.c
@@ -52,19 +52,23 @@
 
 static void
 lp_resource_copy(struct pipe_context *pipe,
-                 struct pipe_resource *dst, struct pipe_subresource subdst,
+                 struct pipe_resource *dst, unsigned dst_level,
                  unsigned dstx, unsigned dsty, unsigned dstz,
-                 struct pipe_resource *src, struct pipe_subresource subsrc,
-                 unsigned srcx, unsigned srcy, unsigned srcz,
-                 unsigned width, unsigned height)
+                 struct pipe_resource *src, unsigned src_level,
+                 const struct pipe_box *src_box)
 {
-   /* XXX what about the dstz/srcz parameters - zslice wasn't used... */
+   /* XXX this used to ignore srcz/dstz
+    * assume it works the same for cube and 3d
+    */
    struct llvmpipe_resource *src_tex = llvmpipe_resource(src);
    struct llvmpipe_resource *dst_tex = llvmpipe_resource(dst);
    const enum pipe_format format = src_tex->base.format;
+   unsigned width = src_box->width;
+   unsigned height = src_box->height;
+   assert(src_box->depth == 1);
 
    llvmpipe_flush_resource(pipe,
-                           dst, subdst.face, subdst.level,
+                           dst, dst_level, dstz,
                            0, /* flush_flags */
                            FALSE, /* read_only */
                            TRUE, /* cpu_access */
@@ -72,7 +76,7 @@
                            "blit dest");
 
    llvmpipe_flush_resource(pipe,
-                           src, subsrc.face, subsrc.level,
+                           src, src_level, src_box->z,
                            0, /* flush_flags */
                            TRUE, /* read_only */
                            TRUE, /* cpu_access */
@@ -80,9 +84,10 @@
                            "blit src");
 
    /*
-   printf("surface copy from %u to %u: %u,%u to %u,%u %u x %u\n",
-          src_tex->id, dst_tex->id,
-          srcx, srcy, dstx, dsty, width, height);
+   printf("surface copy from %u lvl %u to %u lvl %u: %u,%u,%u to %u,%u,%u %u x %u x %u\n",
+          src_tex->id, src_level, dst_tex->id, dst_level, 
+          src_box->x, src_box->y, src_box->z, dstx, dsty, dstz,
+          src_box->width, src_box->height, src_box->depth);
    */
 
    /* set src tiles to linear layout */
@@ -90,12 +95,13 @@
       unsigned tx, ty, tw, th;
       unsigned x, y;
 
-      adjust_to_tile_bounds(srcx, srcy, width, height, &tx, &ty, &tw, &th);
+      adjust_to_tile_bounds(src_box->x, src_box->y, width, height,
+                            &tx, &ty, &tw, &th);
 
       for (y = 0; y < th; y += TILE_SIZE) {
          for (x = 0; x < tw; x += TILE_SIZE) {
             (void) llvmpipe_get_texture_tile_linear(src_tex,
-                                                    subsrc.face, subsrc.level,
+                                                    src_box->z, src_level,
                                                     LP_TEX_USAGE_READ,
                                                     tx + x, ty + y);
          }
@@ -130,7 +136,7 @@
                usage = LP_TEX_USAGE_READ_WRITE;
 
             (void) llvmpipe_get_texture_tile_linear(dst_tex,
-                                                    subdst.face, subdst.level,
+                                                    dstz, dst_level,
                                                     usage,
                                                     tx + x, ty + y);
          }
@@ -140,22 +146,22 @@
    /* copy */
    {
       const ubyte *src_linear_ptr
-         = llvmpipe_get_texture_image_address(src_tex, subsrc.face,
-                                              subsrc.level,
+         = llvmpipe_get_texture_image_address(src_tex, src_box->z,
+                                              src_level,
                                               LP_TEX_LAYOUT_LINEAR);
       ubyte *dst_linear_ptr
-         = llvmpipe_get_texture_image_address(dst_tex, subdst.face,
-                                              subdst.level,
+         = llvmpipe_get_texture_image_address(dst_tex, dstz,
+                                              dst_level,
                                               LP_TEX_LAYOUT_LINEAR);
 
       if (dst_linear_ptr && src_linear_ptr) {
          util_copy_rect(dst_linear_ptr, format,
-                        llvmpipe_resource_stride(&dst_tex->base, subdst.level),
+                        llvmpipe_resource_stride(&dst_tex->base, dst_level),
                         dstx, dsty,
                         width, height,
                         src_linear_ptr,
-                        llvmpipe_resource_stride(&src_tex->base, subsrc.level),
-                        srcx, srcy);
+                        llvmpipe_resource_stride(&src_tex->base, src_level),
+                        src_box->x, src_box->y);
       }
    }
 }
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index f78cd60..9753da5 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -243,6 +243,7 @@
       /* other data (vertex buffer, const buffer, etc) */
       const enum pipe_format format = templat->format;
       const uint w = templat->width0 / util_format_get_blockheight(format);
+      /* XXX buffers should only have one dimension, those values should be 1 */
       const uint h = templat->height0 / util_format_get_blockwidth(format);
       const uint d = templat->depth0;
       const uint bpp = util_format_get_blocksize(format);
@@ -330,17 +331,16 @@
  */
 void *
 llvmpipe_resource_map(struct pipe_resource *resource,
-		      unsigned face,
-		      unsigned level,
-		      unsigned zslice,
+                      unsigned level,
+                      unsigned layer,
                       enum lp_texture_usage tex_usage,
                       enum lp_texture_layout layout)
 {
    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
    uint8_t *map;
 
-   assert(face < 6);
    assert(level < LP_MAX_TEXTURE_LEVELS);
+   assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
 
    assert(tex_usage == LP_TEX_USAGE_READ ||
           tex_usage == LP_TEX_USAGE_READ_WRITE ||
@@ -364,9 +364,8 @@
          dt_usage = PIPE_TRANSFER_READ_WRITE;
       }
 
-      assert(face == 0);
       assert(level == 0);
-      assert(zslice == 0);
+      assert(layer == 0);
 
       /* FIXME: keep map count? */
       map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
@@ -382,15 +381,8 @@
       return map2;
    }
    else if (resource_is_texture(resource)) {
-      /* regular texture */
-      if (resource->target != PIPE_TEXTURE_CUBE) {
-         assert(face == 0);
-      }
-      if (resource->target != PIPE_TEXTURE_3D) {
-         assert(zslice == 0);
-      }
 
-      map = llvmpipe_get_texture_image(lpr, face + zslice, level,
+      map = llvmpipe_get_texture_image(lpr, layer, level,
                                        tex_usage, layout);
       return map;
    }
@@ -405,9 +397,8 @@
  */
 void
 llvmpipe_resource_unmap(struct pipe_resource *resource,
-                       unsigned face,
                        unsigned level,
-                       unsigned zslice)
+                       unsigned layer)
 {
    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
 
@@ -416,12 +407,11 @@
       struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen);
       struct sw_winsys *winsys = lp_screen->winsys;
 
-      assert(face == 0);
       assert(level == 0);
-      assert(zslice == 0);
+      assert(layer == 0);
 
       /* make sure linear image is up to date */
-      (void) llvmpipe_get_texture_image(lpr, face + zslice, level,
+      (void) llvmpipe_get_texture_image(lpr, layer, level,
                                         LP_TEX_USAGE_READ,
                                         LP_TEX_LAYOUT_LINEAR);
 
@@ -521,34 +511,35 @@
 
 
 static struct pipe_surface *
-llvmpipe_get_tex_surface(struct pipe_screen *screen,
-                         struct pipe_resource *pt,
-                         unsigned face, unsigned level, unsigned zslice,
-                         unsigned usage)
+llvmpipe_create_surface(struct pipe_context *pipe,
+                        struct pipe_resource *pt,
+                        const struct pipe_surface *surf_tmpl)
 {
    struct pipe_surface *ps;
 
-   assert(level <= pt->last_level);
+   assert(surf_tmpl->u.tex.level <= pt->last_level);
 
    ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
       pipe_reference_init(&ps->reference, 1);
       pipe_resource_reference(&ps->texture, pt);
-      ps->format = pt->format;
-      ps->width = u_minify(pt->width0, level);
-      ps->height = u_minify(pt->height0, level);
-      ps->usage = usage;
+      ps->context = pipe;
+      ps->format = surf_tmpl->format;
+      ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
+      ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
+      ps->usage = surf_tmpl->usage;
 
-      ps->face = face;
-      ps->level = level;
-      ps->zslice = zslice;
+      ps->u.tex.level = surf_tmpl->u.tex.level;
+      ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+      ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
    }
    return ps;
 }
 
 
 static void 
-llvmpipe_tex_surface_destroy(struct pipe_surface *surf)
+llvmpipe_surface_destroy(struct pipe_context *pipe,
+                         struct pipe_surface *surf)
 {
    /* Effectively do the texture_update work here - if texture images
     * needed post-processing to put them into hardware layout, this is
@@ -562,17 +553,17 @@
 
 static struct pipe_transfer *
 llvmpipe_get_transfer(struct pipe_context *pipe,
-		      struct pipe_resource *resource,
-		      struct pipe_subresource sr,
-		      unsigned usage,
-		      const struct pipe_box *box)
+                      struct pipe_resource *resource,
+                      unsigned level,
+                      unsigned usage,
+                      const struct pipe_box *box)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
    struct llvmpipe_resource *lprex = llvmpipe_resource(resource);
    struct llvmpipe_transfer *lpr;
 
    assert(resource);
-   assert(sr.level <= resource->last_level);
+   assert(level <= resource->last_level);
 
    /*
     * Transfers, like other pipe operations, must happen in order, so flush the
@@ -582,7 +573,8 @@
       boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
       boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
       if (!llvmpipe_flush_resource(pipe, resource,
-                                   sr.face, sr.level,
+                                   level,
+                                   box->depth > 1 ? -1 : box->z,
                                    0, /* flush_flags */
                                    read_only,
                                    TRUE, /* cpu_access */
@@ -604,9 +596,9 @@
       struct pipe_transfer *pt = &lpr->base;
       pipe_resource_reference(&pt->resource, resource);
       pt->box = *box;
-      pt->sr = sr;
-      pt->stride = lprex->row_stride[sr.level];
-      pt->slice_stride = lprex->img_stride[sr.level];
+      pt->level = level;
+      pt->stride = lprex->row_stride[level];
+      pt->layer_stride = lprex->img_stride[level];
       pt->usage = usage;
 
       return pt;
@@ -640,8 +632,7 @@
    enum lp_texture_usage tex_usage;
    const char *mode;
 
-   assert(transfer->sr.face < 6);
-   assert(transfer->sr.level < LP_MAX_TEXTURE_LEVELS);
+   assert(transfer->level < LP_MAX_TEXTURE_LEVELS);
 
    /*
    printf("tex_transfer_map(%d, %d  %d x %d of %d x %d,  usage %d )\n",
@@ -671,9 +662,8 @@
    format = lpr->base.format;
 
    map = llvmpipe_resource_map(transfer->resource,
-			       transfer->sr.face,
-			       transfer->sr.level,
-			       transfer->box.z,
+                               transfer->level,
+                               transfer->box.z,
                                tex_usage, LP_TEX_LAYOUT_LINEAR);
 
 
@@ -685,7 +675,7 @@
        */
       screen->timestamp++;
    }
-   
+
    map +=
       transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
       transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
@@ -701,21 +691,20 @@
    assert(transfer->resource);
 
    llvmpipe_resource_unmap(transfer->resource,
-			   transfer->sr.face,
-			   transfer->sr.level,
-			   transfer->box.z);
+                           transfer->level,
+                           transfer->box.z);
 }
 
 static unsigned int
 llvmpipe_is_resource_referenced( struct pipe_context *pipe,
-				struct pipe_resource *presource,
-				unsigned face, unsigned level)
+                                 struct pipe_resource *presource,
+                                 unsigned level, int layer)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
 
    if (presource->target == PIPE_BUFFER)
       return PIPE_UNREFERENCED;
-   
+
    return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
 }
 
@@ -745,6 +734,7 @@
    buffer->base.width0 = bytes;
    buffer->base.height0 = 1;
    buffer->base.depth0 = 1;
+   buffer->base.array_size = 1;
    buffer->userBuffer = TRUE;
    buffer->data = ptr;
 
@@ -1401,8 +1391,6 @@
    screen->resource_get_handle = llvmpipe_resource_get_handle;
    screen->user_buffer_create = llvmpipe_user_buffer_create;
 
-   screen->get_tex_surface = llvmpipe_get_tex_surface;
-   screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
 }
 
 
@@ -1417,4 +1405,7 @@
  
    pipe->transfer_flush_region = u_default_transfer_flush_region;
    pipe->transfer_inline_write = u_default_transfer_inline_write;
+
+   pipe->create_surface = llvmpipe_create_surface;
+   pipe->surface_destroy = llvmpipe_surface_destroy;
 }
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h
index 4e4a65d..b789c0f 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.h
+++ b/src/gallium/drivers/llvmpipe/lp_texture.h
@@ -172,17 +172,15 @@
 
 void *
 llvmpipe_resource_map(struct pipe_resource *resource,
-		      unsigned face_slice,
-		      unsigned level,
-		      unsigned zslice,
+                      unsigned level,
+                      unsigned layer,
                       enum lp_texture_usage tex_usage,
                       enum lp_texture_layout layout);
 
 void
 llvmpipe_resource_unmap(struct pipe_resource *resource,
-                       unsigned face_slice,
                        unsigned level,
-                       unsigned zslice);
+                       unsigned layer);
 
 
 void *
diff --git a/src/gallium/drivers/noop/noop_pipe.c b/src/gallium/drivers/noop/noop_pipe.c
index fb5cdb4..c9c463f 100644
--- a/src/gallium/drivers/noop/noop_pipe.c
+++ b/src/gallium/drivers/noop/noop_pipe.c
@@ -83,7 +83,7 @@
 
 static unsigned noop_is_resource_referenced(struct pipe_context *pipe,
 						struct pipe_resource *resource,
-						unsigned face, unsigned level)
+						unsigned level, int layer)
 {
 	return PIPE_UNREFERENCED;
 }
@@ -193,7 +193,7 @@
  */
 static struct pipe_transfer *noop_get_transfer(struct pipe_context *context,
 						struct pipe_resource *resource,
-						struct pipe_subresource sr,
+						unsigned level,
 						enum pipe_transfer_usage usage,
 						const struct pipe_box *box)
 {
@@ -203,11 +203,11 @@
 	if (transfer == NULL)
 		return NULL;
 	pipe_resource_reference(&transfer->resource, resource);
-	transfer->sr = sr;
+	transfer->level = level;
 	transfer->usage = usage;
 	transfer->box = *box;
 	transfer->stride = 1;
-	transfer->slice_stride = 1;
+	transfer->layer_stride = 1;
 	return transfer;
 }
 
@@ -239,12 +239,12 @@
 
 static void noop_transfer_inline_write(struct pipe_context *pipe,
 					struct pipe_resource *resource,
-					struct pipe_subresource sr,
+					unsigned level,
 					unsigned usage,
 					const struct pipe_box *box,
 					const void *data,
 					unsigned stride,
-					unsigned slice_stride)
+					unsigned layer_stride)
 {
 }
 
@@ -277,12 +277,11 @@
 
 static void noop_resource_copy_region(struct pipe_context *ctx,
 				      struct pipe_resource *dst,
-				      struct pipe_subresource subdst,
+				      unsigned dst_level,
 				      unsigned dstx, unsigned dsty, unsigned dstz,
 				      struct pipe_resource *src,
-				      struct pipe_subresource subsrc,
-				      unsigned srcx, unsigned srcy, unsigned srcz,
-				      unsigned width, unsigned height)
+				      unsigned src_level,
+				      const struct pipe_box *src_box)
 {
 }
 
@@ -332,46 +331,14 @@
 	return ctx;
 }
 
-/*
- * texture
- */
-static struct pipe_surface *noop_get_tex_surface(struct pipe_screen *screen,
-						struct pipe_resource *texture,
-						unsigned face, unsigned level,
-						unsigned zslice, unsigned flags)
-{
-	struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
-
-	if (surface == NULL)
-		return NULL;
-	pipe_reference_init(&surface->reference, 1);
-	pipe_resource_reference(&surface->texture, texture);
-	surface->format = texture->format;
-	surface->width = texture->width0;
-	surface->height = texture->height0;
-	surface->offset = 0;
-	surface->usage = flags;
-	surface->zslice = zslice;
-	surface->texture = texture;
-	surface->face = face;
-	surface->level = level;
-
-	return surface;
-}
-
-static void noop_tex_surface_destroy(struct pipe_surface *surface)
-{
-	pipe_resource_reference(&surface->texture, NULL);
-	FREE(surface);
-}
-
 
 /*
  * pipe_screen
  */
 static void noop_flush_frontbuffer(struct pipe_screen *_screen,
-					struct pipe_surface *surface,
-					void *context_private)
+				   struct pipe_resource *resource,
+				   unsigned level, unsigned layer,
+				   void *context_private)
 {
 }
 
@@ -537,8 +504,6 @@
 	screen->get_paramf = noop_get_paramf;
 	screen->is_format_supported = noop_is_format_supported;
 	screen->context_create = noop_create_context;
-	screen->get_tex_surface = noop_get_tex_surface;
-	screen->tex_surface_destroy = noop_tex_surface_destroy;
 	screen->resource_create = noop_resource_create;
 	screen->resource_from_handle = noop_resource_from_handle;
 	screen->resource_get_handle = noop_resource_get_handle;
diff --git a/src/gallium/drivers/noop/noop_state.c b/src/gallium/drivers/noop/noop_state.c
index 048ed42..5c62fc1 100644
--- a/src/gallium/drivers/noop/noop_state.c
+++ b/src/gallium/drivers/noop/noop_state.c
@@ -101,6 +101,28 @@
 	return sampler_view;
 }
 
+static struct pipe_surface *noop_create_surface(struct pipe_context *ctx,
+						struct pipe_resource *texture,
+						const struct pipe_surface *surf_tmpl)
+{
+	struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
+
+	if (surface == NULL)
+		return NULL;
+	pipe_reference_init(&surface->reference, 1);
+	pipe_resource_reference(&surface->texture, texture);
+	surface->context = ctx;
+	surface->format = surf_tmpl->format;
+	surface->width = texture->width0;
+	surface->height = texture->height0;
+	surface->usage = surf_tmpl->usage;
+	surface->texture = texture;
+	surface->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+	surface->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
+	surface->u.tex.level = surf_tmpl->u.tex.level;
+
+	return surface;
+}
 static void noop_set_vs_sampler_view(struct pipe_context *ctx, unsigned count,
 					struct pipe_sampler_view **views)
 {
@@ -163,6 +185,14 @@
 	FREE(state);
 }
 
+
+static void noop_surface_destroy(struct pipe_context *ctx,
+				 struct pipe_surface *surface)
+{
+	pipe_resource_reference(&surface->texture, NULL);
+	FREE(surface);
+}
+
 static void noop_bind_state(struct pipe_context *ctx, void *state)
 {
 }
@@ -221,6 +251,7 @@
 	ctx->create_rasterizer_state = noop_create_rs_state;
 	ctx->create_sampler_state = noop_create_sampler_state;
 	ctx->create_sampler_view = noop_create_sampler_view;
+	ctx->create_surface = noop_create_surface;
 	ctx->create_vertex_elements_state = noop_create_vertex_elements;
 	ctx->create_vs_state = noop_create_shader_state;
 	ctx->bind_blend_state = noop_bind_state;
@@ -252,5 +283,6 @@
 	ctx->set_vertex_sampler_views = noop_set_vs_sampler_view;
 	ctx->set_viewport_state = noop_set_viewport_state;
 	ctx->sampler_view_destroy = noop_sampler_view_destroy;
+	ctx->surface_destroy = noop_surface_destroy;
 	ctx->draw_vbo = noop_draw_vbo;
 }
diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c
index dacfee9..45356f9 100644
--- a/src/gallium/drivers/nv50/nv50_buffer.c
+++ b/src/gallium/drivers/nv50/nv50_buffer.c
@@ -136,6 +136,7 @@
 	buffer->base.width0 = bytes;
 	buffer->base.height0 = 1;
 	buffer->base.depth0 = 1;
+	buffer->base.array_size = 1;
 
 	buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes);
 	if (!buffer->bo)
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index bf6a577..b2b0b72 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -108,6 +108,7 @@
 
 struct nv50_surface {
 	struct pipe_surface base;
+	unsigned offset;
 };
 
 static INLINE struct nv50_surface *
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index dd0e8fd..309b650 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -276,46 +276,53 @@
  */
 
 struct pipe_surface *
-nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
-			 unsigned face, unsigned level, unsigned zslice,
-			 unsigned flags)
+nv50_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
+			 const struct pipe_surface *surf_tmpl)
 {
+	unsigned level = surf_tmpl->u.tex.level;
 	struct nv50_miptree *mt = nv50_miptree(pt);
 	struct nv50_miptree_level *lvl = &mt->level[level];
-	struct pipe_surface *ps;
-	unsigned img = 0;
+	struct nv50_surface *ns;
+	unsigned img = 0, zslice = 0;
 
+	assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
+
+	/* XXX can't unify these here? */
 	if (pt->target == PIPE_TEXTURE_CUBE)
-		img = face;
+		img = surf_tmpl->u.tex.first_layer;
+	else if (pt->target == PIPE_TEXTURE_3D)
+		zslice = surf_tmpl->u.tex.first_layer;
 
-	ps = CALLOC_STRUCT(pipe_surface);
-	if (!ps)
+	ns = CALLOC_STRUCT(nv50_surface);
+	if (!ns)
 		return NULL;
-	pipe_resource_reference(&ps->texture, pt);
-	ps->format = pt->format;
-	ps->width = u_minify(pt->width0, level);
-	ps->height = u_minify(pt->height0, level);
-	ps->usage = flags;
-	pipe_reference_init(&ps->reference, 1);
-	ps->face = face;
-	ps->level = level;
-	ps->zslice = zslice;
-	ps->offset = lvl->image_offset[img];
+	pipe_resource_reference(&ns->base.texture, pt);
+	ns->base.context = pipe;
+	ns->base.format = pt->format;
+	ns->base.width = u_minify(pt->width0, level);
+	ns->base.height = u_minify(pt->height0, level);
+	ns->base.usage = surf_tmpl->usage;
+	pipe_reference_init(&ns->base.reference, 1);
+	ns->base.u.tex.level = level;
+	ns->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+	ns->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
+	ns->offset = lvl->image_offset[img];
 
 	if (pt->target == PIPE_TEXTURE_3D) {
-		unsigned nb_h = util_format_get_nblocksy(pt->format, ps->height);
-		ps->offset += get_zslice_offset(lvl->tile_mode, zslice,
+		unsigned nb_h = util_format_get_nblocksy(pt->format, ns->base.height);
+		ns->offset += get_zslice_offset(lvl->tile_mode, zslice,
 						lvl->pitch, nb_h);
 	}
 
-	return ps;
+	return &ns->base;
 }
 
 void
-nv50_miptree_surface_del(struct pipe_surface *ps)
+nv50_miptree_surface_del(struct pipe_context *pipe,
+			 struct pipe_surface *ps)
 {
 	struct nv50_surface *s = nv50_surface(ps);
 
-	pipe_resource_reference(&ps->texture, NULL);
+	pipe_resource_reference(&s->base.texture, NULL);
 	FREE(s);
 }
diff --git a/src/gallium/drivers/nv50/nv50_resource.c b/src/gallium/drivers/nv50/nv50_resource.c
index cfdb604..6c0a969 100644
--- a/src/gallium/drivers/nv50/nv50_resource.c
+++ b/src/gallium/drivers/nv50/nv50_resource.c
@@ -15,7 +15,7 @@
 static unsigned int
 nv50_resource_is_referenced(struct pipe_context *pipe,
 			    struct pipe_resource *resource,
-			    unsigned face, unsigned level)
+			    unsigned level, int layer)
 {
 	return nouveau_reference_flags(nv50_resource(resource)->bo);
 }
@@ -51,6 +51,9 @@
 	pcontext->transfer_destroy = u_transfer_destroy_vtbl;
 	pcontext->transfer_inline_write = u_transfer_inline_write_vtbl;
 	pcontext->is_resource_referenced = nv50_resource_is_referenced;
+
+	pcontext->create_surface = nv50_miptree_surface_new;
+	pcontext->surface_destroy = nv50_miptree_surface_del;
 }
 
 void
@@ -61,7 +64,4 @@
 	pscreen->resource_get_handle = u_resource_get_handle_vtbl;
 	pscreen->resource_destroy = u_resource_destroy_vtbl;
 	pscreen->user_buffer_create = nv50_user_buffer_create;
-   
-	pscreen->get_tex_surface = nv50_miptree_surface_new;
-	pscreen->tex_surface_destroy = nv50_miptree_surface_del;
 }
diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h
index f435a58..4b2a75e 100644
--- a/src/gallium/drivers/nv50/nv50_resource.h
+++ b/src/gallium/drivers/nv50/nv50_resource.h
@@ -87,12 +87,11 @@
 
 
 struct pipe_surface *
-nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
-			 unsigned face, unsigned level, unsigned zslice,
-			 unsigned flags);
+nv50_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
+			 const struct pipe_surface *surf_tmpl);
 
 void
-nv50_miptree_surface_del(struct pipe_surface *ps);
+nv50_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps);
 
 
 #endif
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index 16c2dab..ae02143 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -63,13 +63,13 @@
 		so_data  (so, fb->cbufs[i]->height);
 
 		so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
-		so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM |
+		so_reloc (so, bo, ((struct nv50_surface *)fb->cbufs[i])->offset, NOUVEAU_BO_VRAM |
 			      NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0);
-		so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM |
+		so_reloc (so, bo, ((struct nv50_surface *)fb->cbufs[i])->offset, NOUVEAU_BO_VRAM |
 			      NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0);
 		so_data  (so, nv50_format_table[fb->cbufs[i]->format].rt);
 		so_data  (so, nv50_miptree(pt)->
-			      level[fb->cbufs[i]->level].tile_mode << 4);
+			      level[fb->cbufs[i]->u.tex.level].tile_mode << 4);
 		so_data(so, 0x00000000);
 
 		so_method(so, tesla, NV50TCL_RT_ARRAY_MODE, 1);
@@ -92,13 +92,13 @@
 		assert(nv50_format_table[fb->zsbuf->format].rt);
 
 		so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
-		so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM |
+		so_reloc (so, bo, ((struct nv50_surface *)(fb->zsbuf))->offset, NOUVEAU_BO_VRAM |
 			      NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0);
-		so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM |
+		so_reloc (so, bo, ((struct nv50_surface *)(fb->zsbuf))->offset, NOUVEAU_BO_VRAM |
 			      NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0);
 		so_data  (so, nv50_format_table[fb->zsbuf->format].rt);
 		so_data  (so, nv50_miptree(pt)->
-			      level[fb->zsbuf->level].tile_mode << 4);
+			      level[fb->zsbuf->u.tex.level].tile_mode << 4);
 		so_data  (so, 0x00000000);
 
 		so_method(so, tesla, NV50TCL_ZETA_ENABLE, 1);
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index f70c138..ce48022 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -97,23 +97,23 @@
  		OUT_RING  (chan, format);
  		OUT_RING  (chan, 1);
  		BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
-		OUT_RING  (chan, mt->level[ps->level].pitch);
+		OUT_RING  (chan, mt->level[ps->u.tex.level].pitch);
  		OUT_RING  (chan, ps->width);
  		OUT_RING  (chan, ps->height);
- 		OUT_RELOCh(chan, bo, ps->offset, flags);
- 		OUT_RELOCl(chan, bo, ps->offset, flags);
+ 		OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
+ 		OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
  	} else {
  		BEGIN_RING(chan, eng2d, mthd, 5);
  		OUT_RING  (chan, format);
  		OUT_RING  (chan, 0);
-		OUT_RING  (chan, mt->level[ps->level].tile_mode << 4);
+		OUT_RING  (chan, mt->level[ps->u.tex.level].tile_mode << 4);
  		OUT_RING  (chan, 1);
  		OUT_RING  (chan, 0);
  		BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
  		OUT_RING  (chan, ps->width);
  		OUT_RING  (chan, ps->height);
- 		OUT_RELOCh(chan, bo, ps->offset, flags);
- 		OUT_RELOCl(chan, bo, ps->offset, flags);
+ 		OUT_RELOCh(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
+ 		OUT_RELOCl(chan, bo, ((struct nv50_surface *)ps)->offset, flags);
  	}
  
 #if 0
@@ -173,30 +173,41 @@
 
 static void
 nv50_surface_copy(struct pipe_context *pipe,
-		  struct pipe_resource *dest, struct pipe_subresource subdst,
+		  struct pipe_resource *dest, unsigned dst_level,
 		  unsigned destx, unsigned desty, unsigned destz,
-		  struct pipe_resource *src, struct pipe_subresource subsrc,
-		  unsigned srcx, unsigned srcy, unsigned srcz,
-		  unsigned width, unsigned height)
+		  struct pipe_resource *src, unsigned src_level,
+		  const struct pipe_box *src_box)
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
 	struct nv50_screen *screen = nv50->screen;
-	struct pipe_surface *ps_dst, *ps_src;
+	struct pipe_surface *ps_dst, *ps_src, surf_tmpl;
+
 
 	assert((src->format == dest->format) ||
 	       (nv50_2d_format_faithful(src->format) &&
 		nv50_2d_format_faithful(dest->format)));
+	assert(src_box->depth == 1);
 
-	ps_src = nv50_miptree_surface_new(pipe->screen, src, subsrc.face,
-					  subsrc.level, srcz, 0 /* bind flags */);
-	ps_dst = nv50_miptree_surface_new(pipe->screen, dest, subdst.face,
-					  subdst.level, destz, 0 /* bindflags */);
+	memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+	surf_tmpl.format = src->format;
+	surf_tmpl.usage = 0; /* no bind flag - not a surface */
+	surf_tmpl.u.tex.level = src_level;
+	surf_tmpl.u.tex.first_layer = src_box->z;
+	surf_tmpl.u.tex.last_layer = src_box->z;
+	/* XXX really need surfaces here? */
+	ps_src = nv50_miptree_surface_new(pipe, src, &surf_tmpl);
+	surf_tmpl.format = dest->format;
+	surf_tmpl.usage = 0; /* no bind flag - not a surface */
+	surf_tmpl.u.tex.level = dst_level;
+	surf_tmpl.u.tex.first_layer = destz;
+	surf_tmpl.u.tex.last_layer = destz;
+	ps_dst = nv50_miptree_surface_new(pipe, dest, &surf_tmpl);
 
-	nv50_surface_do_copy(screen, ps_dst, destx, desty, ps_src, srcx,
-			     srcy, width, height);
+	nv50_surface_do_copy(screen, ps_dst, destx, desty, ps_src, src_box->x,
+			     src_box->y, src_box->width, src_box->height);
 
-	nv50_miptree_surface_del(ps_src);
-	nv50_miptree_surface_del(ps_dst);
+	nv50_miptree_surface_del(pipe, ps_src);
+	nv50_miptree_surface_del(pipe, ps_dst);
 }
 
 static void
@@ -225,10 +236,10 @@
 	BEGIN_RING(chan, tesla, NV50TCL_RT_CONTROL, 1);
 	OUT_RING  (chan, 1);
 	BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
-	OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-	OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 	OUT_RING  (chan, nv50_format_table[dst->format].rt);
-	OUT_RING  (chan, mt->level[dst->level].tile_mode << 4);
+	OUT_RING  (chan, mt->level[dst->u.tex.level].tile_mode << 4);
 	OUT_RING  (chan, 0);
 	BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
 	OUT_RING  (chan, dst->width);
@@ -281,10 +292,10 @@
 		return;
 
 	BEGIN_RING(chan, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
-	OUT_RELOCh(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-	OUT_RELOCl(chan, bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCh(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+	OUT_RELOCl(chan, bo, ((struct nv50_surface *)dst)->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 	OUT_RING  (chan, nv50_format_table[dst->format].rt);
-	OUT_RING  (chan, mt->level[dst->level].tile_mode << 4);
+	OUT_RING  (chan, mt->level[dst->u.tex.level].tile_mode << 4);
 	OUT_RING  (chan, 0);
 	BEGIN_RING(chan, tesla, NV50TCL_ZETA_ENABLE, 1);
 	OUT_RING  (chan, 1);
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
index 658324e..9243f9e 100644
--- a/src/gallium/drivers/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -106,7 +106,7 @@
 
 	tic[6] = 0x03000000;
 
-	tic[7] = (view->pipe.last_level << 4) | view->pipe.first_level;
+	tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
 
 	return TRUE;
 }
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index 0cc2f4a..bf5af4d 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -126,20 +126,23 @@
 struct pipe_transfer *
 nv50_miptree_transfer_new(struct pipe_context *pcontext,
 			  struct pipe_resource *pt,
-			  struct pipe_subresource sr,
+			  unsigned level,
 			  unsigned usage,
 			  const struct pipe_box *box)
 {
         struct pipe_screen *pscreen = pcontext->screen;
 	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
 	struct nv50_miptree *mt = nv50_miptree(pt);
-	struct nv50_miptree_level *lvl = &mt->level[sr.level];
+	struct nv50_miptree_level *lvl = &mt->level[level];
 	struct nv50_transfer *tx;
-	unsigned nx, ny, image = 0;
+	unsigned nx, ny, image = 0, boxz = 0;
 	int ret;
 
+	/* XXX can't unify these here? */
 	if (pt->target == PIPE_TEXTURE_CUBE)
-		image = sr.face;
+		image = box->z;
+	else if (pt->target == PIPE_TEXTURE_3D)
+		boxz = box->z;
 
 	tx = CALLOC_STRUCT(nv50_transfer);
 	if (!tx)
@@ -151,21 +154,21 @@
 
 
 	pipe_resource_reference(&tx->base.resource, pt);
-	tx->base.sr = sr;
+	tx->base.level = level;
 	tx->base.usage = usage;
 	tx->base.box = *box;
-	tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, sr.level));
-	tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, sr.level));
+	tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, level));
+	tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, level));
 	tx->base.stride = tx->nblocksx * util_format_get_blocksize(pt->format);
 	tx->base.usage = usage;
 
 	tx->level_pitch = lvl->pitch;
-	tx->level_width = u_minify(mt->base.base.width0, sr.level);
-	tx->level_height = u_minify(mt->base.base.height0, sr.level);
-	tx->level_depth = u_minify(mt->base.base.depth0, sr.level);
+	tx->level_width = u_minify(mt->base.base.width0, level);
+	tx->level_height = u_minify(mt->base.base.height0, level);
+	tx->level_depth = u_minify(mt->base.base.depth0, level);
 	tx->level_offset = lvl->image_offset[image];
 	tx->level_tiling = lvl->tile_mode;
-	tx->level_z = box->z;
+	tx->level_z = boxz;
 	tx->level_x = util_format_get_nblocksx(pt->format, box->x);
 	tx->level_y = util_format_get_nblocksy(pt->format, box->y);
 	ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
@@ -181,7 +184,7 @@
 
 		nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
 					tx->level_pitch, tx->level_tiling,
-					box->x, box->y, box->z,
+					box->x, box->y, boxz,
 					tx->nblocksx, tx->nblocksy,
 					tx->level_depth,
 					tx->bo, 0,
diff --git a/src/gallium/drivers/nv50/nv50_transfer.h b/src/gallium/drivers/nv50/nv50_transfer.h
index 6635035..6699bf5 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.h
+++ b/src/gallium/drivers/nv50/nv50_transfer.h
@@ -8,7 +8,7 @@
 struct pipe_transfer *
 nv50_miptree_transfer_new(struct pipe_context *pcontext,
 			  struct pipe_resource *pt,
-			  struct pipe_subresource sr,
+			  unsigned level,
 			  unsigned usage,
 			  const struct pipe_box *box);
 void
diff --git a/src/gallium/drivers/nvfx/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c
index d6ede5b..951fb20 100644
--- a/src/gallium/drivers/nvfx/nv30_fragtex.c
+++ b/src/gallium/drivers/nvfx/nv30_fragtex.c
@@ -37,12 +37,12 @@
 	struct pipe_resource* pt = sv->base.texture;
 	struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
 	unsigned txf;
-	unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level;
+	unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.u.tex.first_level;
 
 	assert(tf->fmt[0] >= 0);
 
 	txf = sv->u.init_fmt;
-	txf |= (level != sv->base.last_level ? NV30_3D_TEX_FORMAT_MIPMAP : 0);
+	txf |= (level != sv->base.u.tex.last_level ? NV30_3D_TEX_FORMAT_MIPMAP : 0);
 	txf |= util_logbase2(u_minify(pt->width0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT;
 	txf |= util_logbase2(u_minify(pt->height0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT;
 	txf |= util_logbase2(u_minify(pt->depth0, level)) << NV30_3D_TEX_FORMAT_BASE_SIZE_W__SHIFT;
@@ -60,8 +60,8 @@
 	else
 		sv->u.nv30.rect = !!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR);
 
-	sv->lod_offset = sv->base.first_level - level;
-	sv->max_lod_limit = sv->base.last_level - level;
+	sv->lod_offset = sv->base.u.tex.first_level - level;
+	sv->max_lod_limit = sv->base.u.tex.last_level - level;
 }
 
 void
diff --git a/src/gallium/drivers/nvfx/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c
index d4fb737..e8ab403 100644
--- a/src/gallium/drivers/nvfx/nv40_fragtex.c
+++ b/src/gallium/drivers/nvfx/nv40_fragtex.c
@@ -46,7 +46,7 @@
 	struct nvfx_miptree* mt = (struct nvfx_miptree*)pt;
 	struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
 	unsigned txf;
-	unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level;
+	unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.u.tex.first_level;
 	assert(tf->fmt[4] >= 0);
 
 	txf = sv->u.init_fmt;
@@ -54,7 +54,7 @@
 	if(pt->target == PIPE_TEXTURE_CUBE)
 		txf |= ((pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT);
 	else
-		txf |= (((sv->base.last_level - sv->base.first_level) + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT);
+		txf |= (((sv->base.u.tex.last_level - sv->base.u.tex.first_level) + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT);
 
 	if (!mt->linear_pitch)
 		sv->u.nv40.npot_size2 = 0;
@@ -68,8 +68,8 @@
 
 	sv->u.nv40.npot_size2 |= (u_minify(pt->depth0, level) << NV40_3D_TEX_SIZE1_DEPTH__SHIFT);
 
-	sv->lod_offset = (sv->base.first_level - level) * 256;
-	sv->max_lod_limit = (sv->base.last_level - level) * 256;
+	sv->lod_offset = (sv->base.u.tex.first_level - level) * 256;
+	sv->max_lod_limit = (sv->base.u.tex.last_level - level) * 256;
 }
 
 void
diff --git a/src/gallium/drivers/nvfx/nvfx_buffer.c b/src/gallium/drivers/nvfx/nvfx_buffer.c
index 041099e..b407429 100644
--- a/src/gallium/drivers/nvfx/nvfx_buffer.c
+++ b/src/gallium/drivers/nvfx/nvfx_buffer.c
@@ -64,6 +64,7 @@
 	buffer->base.base.width0 = bytes;
 	buffer->base.base.height0 = 1;
 	buffer->base.base.depth0 = 1;
+	buffer->base.base.array_size = 1;
 	buffer->data = ptr;
 	buffer->size = bytes;
 	buffer->bytes_to_draw_until_static = bytes * screen->static_reuse_threshold;
diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c
index 1d6b4e2..fd0aff6 100644
--- a/src/gallium/drivers/nvfx/nvfx_fragtex.c
+++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c
@@ -122,8 +122,8 @@
 	}
 	else
 	{
-		sv->offset = nvfx_subresource_offset(pt, 0, sv->base.first_level, 0);
-		sv->npot_size = (u_minify(pt->width0, sv->base.first_level) << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | u_minify(pt->height0, sv->base.first_level);
+		sv->offset = nvfx_subresource_offset(pt, 0, sv->base.u.tex.first_level, 0);
+		sv->npot_size = (u_minify(pt->width0, sv->base.u.tex.first_level) << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | u_minify(pt->height0, sv->base.u.tex.first_level);
 
 		/* apparently, we need to ignore the t coordinate for 1D textures to fix piglit tex1d-2dborder */
 		if(pt->target == PIPE_TEXTURE_1D)
diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c
index 7677fde..db48025 100644
--- a/src/gallium/drivers/nvfx/nvfx_miptree.c
+++ b/src/gallium/drivers/nvfx/nvfx_miptree.c
@@ -190,25 +190,27 @@
 }
 
 struct pipe_surface *
-nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
-			 unsigned face, unsigned level, unsigned zslice,
-			 unsigned flags)
+nvfx_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
+			 const struct pipe_surface *surf_tmpl)
 {
 	struct nvfx_miptree* mt = (struct nvfx_miptree*)pt;
 	struct nvfx_surface *ns;
+	unsigned level = surf_tmpl->u.tex.level;
 
-	ns = (struct nvfx_surface*)util_surfaces_get(&mt->surfaces, sizeof(struct nvfx_surface), pscreen, pt, face, level, zslice, flags);
-	if(ns->base.base.offset == ~0) {
+	assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
+	ns = (struct nvfx_surface*)util_surfaces_get(&mt->surfaces, sizeof(struct nvfx_surface), NULL, pt,
+						     level, surf_tmpl->u.tex.first_layer, surf_tmpl->usage);
+	if(ns->offset == ~0) {
 		util_dirty_surface_init(&ns->base);
 		ns->pitch = nvfx_subresource_pitch(pt, level);
-		ns->base.base.offset = nvfx_subresource_offset(pt, face, level, zslice);
+		ns->offset = nvfx_subresource_offset(pt, surf_tmpl->u.tex.first_layer, level, surf_tmpl->u.tex.first_layer);
 	}
 
 	return &ns->base.base;
 }
 
 void
-nvfx_miptree_surface_del(struct pipe_surface *ps)
+nvfx_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
 {
 	struct nvfx_surface* ns = (struct nvfx_surface*)ps;
 
diff --git a/src/gallium/drivers/nvfx/nvfx_resource.c b/src/gallium/drivers/nvfx/nvfx_resource.c
index 39ae893..c60a7bb 100644
--- a/src/gallium/drivers/nvfx/nvfx_resource.c
+++ b/src/gallium/drivers/nvfx/nvfx_resource.c
@@ -7,7 +7,7 @@
 static unsigned int
 nvfx_resource_is_referenced(struct pipe_context *pipe,
 			    struct pipe_resource *pr,
-			    unsigned face, unsigned level)
+			    unsigned level, int layer)
 {
 	return !!nouveau_reference_flags(nvfx_resource(pr)->bo);
 }
@@ -59,6 +59,9 @@
 nvfx_init_resource_functions(struct pipe_context *pipe)
 {
 	pipe->is_resource_referenced = nvfx_resource_is_referenced;
+
+	pipe->create_surface = nvfx_miptree_surface_new;
+	pipe->surface_destroy = nvfx_miptree_surface_del;
 }
 
 void
@@ -69,7 +72,4 @@
 	pscreen->resource_get_handle = nvfx_resource_get_handle;
 	pscreen->resource_destroy = nvfx_resource_destroy;
 	pscreen->user_buffer_create = nvfx_user_buffer_create;
-
-	pscreen->get_tex_surface = nvfx_miptree_surface_new;
-	pscreen->tex_surface_destroy = nvfx_miptree_surface_del;
 }
diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h
index 583be4d..070f897 100644
--- a/src/gallium/drivers/nvfx/nvfx_resource.h
+++ b/src/gallium/drivers/nvfx/nvfx_resource.h
@@ -74,6 +74,7 @@
 struct nvfx_surface {
 	struct util_dirty_surface base;
 	unsigned pitch;
+	unsigned offset;
 
 	struct nvfx_miptree* temp;
 };
@@ -116,12 +117,11 @@
 			 struct winsys_handle *whandle);
 
 void
-nvfx_miptree_surface_del(struct pipe_surface *ps);
+nvfx_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps);
 
 struct pipe_surface *
-nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
-			 unsigned face, unsigned level, unsigned zslice,
-			 unsigned flags);
+nvfx_miptree_surface_new(struct pipe_context *pipe, struct pipe_resource *pt,
+			 const struct pipe_surface *surf_tmpl);
 
 /* only for miptrees, don't use for buffers */
 
diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c
index 90eb110..816bb89 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_fb.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c
@@ -7,7 +7,7 @@
 {
 	/* TODO: precompute this in nvfx_surface creation */
 	return (surf->texture->flags & NVFX_RESOURCE_FLAG_LINEAR)
-		&& !(surf->offset & 63)
+		&& !(((struct nvfx_surface*)surf)->offset & 63)
 		&& !(((struct nvfx_surface*)surf)->pitch & 63);
 }
 
@@ -16,8 +16,8 @@
 {
 	/* TODO: precompute this in nvfx_surface creation */
 	return !((struct nvfx_miptree*)surf->texture)->linear_pitch
-		&& (surf->texture->target != PIPE_TEXTURE_3D || u_minify(surf->texture->depth0, surf->level) <= 1)
-		&& !(surf->offset & 127)
+		&& (surf->texture->target != PIPE_TEXTURE_3D || u_minify(surf->texture->depth0, surf->u.tex.level) <= 1)
+		&& !(((struct nvfx_surface*)surf)->offset & 127)
 		&& (surf->width == fb->width)
 		&& (surf->height == fb->height)
 		&& !((struct nvfx_surface*)surf)->temp
@@ -31,7 +31,7 @@
 	if(!ns->temp)
 	{
 		target->bo = ((struct nvfx_miptree*)surf->texture)->base.bo;
-		target->offset = surf->offset;
+		target->offset = ns->offset;
 		target->pitch = align(ns->pitch, 64);
 		assert(target->pitch);
 		return FALSE;
diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c
index 70adebc..7f315e9 100644
--- a/src/gallium/drivers/nvfx/nvfx_surface.c
+++ b/src/gallium/drivers/nvfx/nvfx_surface.c
@@ -99,17 +99,17 @@
 			util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(&surf->base.base), &surf->base);
 	} else {
 		rgn->bo = ((struct nvfx_resource*)surf->base.base.texture)->bo;
-		rgn->offset = surf->base.base.offset;
+		rgn->offset = surf->offset;
 
 		if(surf->base.base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR)
 			rgn->pitch = surf->pitch;
 	        else
 	        {
 		        rgn->pitch = 0;
-		        rgn->z = surf->base.base.zslice;
+		        rgn->z = surf->base.base.u.tex.first_layer;
 		        rgn->w = surf->base.base.width;
 		        rgn->h = surf->base.base.height;
-		        rgn->d = u_minify(surf->base.base.texture->depth0, surf->base.base.level);
+		        rgn->d = u_minify(surf->base.base.texture->depth0, surf->base.base.u.tex.level);
 	        }
 	}
 
@@ -119,11 +119,11 @@
 }
 
 static INLINE void
-nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, struct pipe_subresource sub, unsigned x, unsigned y, unsigned z, bool for_write)
+nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource* pt, unsigned level, unsigned x, unsigned y, unsigned z, bool for_write)
 {
 	if(pt->target != PIPE_BUFFER)
 	{
-		struct nvfx_surface* ns = (struct nvfx_surface*)util_surfaces_peek(&((struct nvfx_miptree*)pt)->surfaces, pt, sub.face, sub.level, z);
+		struct nvfx_surface* ns = (struct nvfx_surface*)util_surfaces_peek(&((struct nvfx_miptree*)pt)->surfaces, pt, level, z);
 		if(ns && util_dirty_surface_is_dirty(&ns->base))
 		{
 			nvfx_region_init_for_surface(rgn, ns, x, y, for_write);
@@ -132,22 +132,22 @@
 	}
 
 	rgn->bo = ((struct nvfx_resource*)pt)->bo;
-	rgn->offset = nvfx_subresource_offset(pt, sub.face, sub.level, z);
+	rgn->offset = nvfx_subresource_offset(pt, z, level, z);
 	rgn->x = x;
 	rgn->y = y;
 
 	if(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
 	{
-		rgn->pitch = nvfx_subresource_pitch(pt, sub.level);
+		rgn->pitch = nvfx_subresource_pitch(pt, level);
 		rgn->z = 0;
 	}
 	else
 	{
 		rgn->pitch = 0;
 		rgn->z = z;
-		rgn->w = u_minify(pt->width0, sub.level);
-		rgn->h = u_minify(pt->height0, sub.level);
-		rgn->d = u_minify(pt->depth0, sub.level);
+		rgn->w = u_minify(pt->width0, level);
+		rgn->h = u_minify(pt->height0, level);
+		rgn->d = u_minify(pt->depth0, level);
 	}
 
 	nvfx_region_set_format(rgn, pt->format);
@@ -234,11 +234,10 @@
 
 static void
 nvfx_resource_copy_region(struct pipe_context *pipe,
-		  struct pipe_resource *dstr, struct pipe_subresource subdst,
-		  unsigned dstx, unsigned dsty, unsigned dstz,
-		  struct pipe_resource *srcr, struct pipe_subresource subsrc,
-		  unsigned srcx, unsigned srcy, unsigned srcz,
-		  unsigned w, unsigned h)
+			  struct pipe_resource *dstr, unsigned dst_level,
+			  unsigned dstx, unsigned dsty, unsigned dstz,
+			  struct pipe_resource *srcr, unsigned src_level,
+			  const struct pipe_box *src_box)
 {
 	static int copy_threshold = -1;
 	struct nv04_2d_context *ctx = nvfx_screen(pipe->screen)->eng2d;
@@ -247,6 +246,8 @@
 	int src_on_gpu;
 	boolean small;
 	int ret;
+	unsigned w = src_box->width;
+	unsigned h = src_box->height;
 
 	if(!w || !h)
 		return;
@@ -257,8 +258,8 @@
 	dst_to_gpu = dstr->usage != PIPE_USAGE_DYNAMIC && dstr->usage != PIPE_USAGE_STAGING;
 	src_on_gpu = nvfx_resource_on_gpu(srcr);
 
-	nvfx_region_init_for_subresource(&dst, dstr, subdst, dstx, dsty, dstz, TRUE);
-	nvfx_region_init_for_subresource(&src, srcr, subsrc, srcx, srcy, srcz, FALSE);
+	nvfx_region_init_for_subresource(&dst, dstr, dst_level, dstx, dsty, dstz, TRUE);
+	nvfx_region_init_for_subresource(&src, srcr, src_level, src_box->x, src_box->y, src_box->z, FALSE);
 	w = util_format_get_stride(dstr->format, w) >> dst.bpps;
 	h = util_format_get_nblocksy(dstr->format, h);
 
@@ -279,7 +280,7 @@
 		 * TODO: perhaps support reinterpreting the formats
 		 */
 		struct blitter_context* blitter = nvfx_get_blitter(pipe, 1);
-		util_blitter_copy_region(blitter, dstr, subdst, dstx, dsty, dstz, srcr, subsrc, srcx, srcy, srcz, w, h, TRUE);
+		util_blitter_copy_region(blitter, dstr, dst_level, dstx, dsty, dstz, srcr, src_level, src_box, TRUE);
 		nvfx_put_blitter(pipe, blitter);
 	}
 	else
@@ -371,7 +372,7 @@
 nvfx_surface_copy_temp(struct pipe_context* pipe, struct pipe_surface* surf, int to_temp)
 {
 	struct nvfx_surface* ns = (struct nvfx_surface*)surf;
-	struct pipe_subresource tempsr, surfsr;
+	struct pipe_box box;
 	struct nvfx_context* nvfx = nvfx_context(pipe);
 	struct nvfx_miptree* temp;
 	unsigned use_vertex_buffers;
@@ -387,15 +388,20 @@
 	use_index_buffer = nvfx->use_index_buffer;
 	base_vertex = nvfx->base_vertex;
 
-	tempsr.face = 0;
-	tempsr.level = 0;
-	surfsr.face = surf->face;
-	surfsr.level = surf->level;
+	box.x = box.y = 0;
+	assert(surf->u.tex.first_layer = surf->u.tex.last_layer);
+	box.width = surf->width;
+	box.height = surf->height;
+	box.depth = 1;
 
-	if(to_temp)
-		nvfx_resource_copy_region(pipe, &temp->base.base, tempsr, 0, 0, 0, surf->texture, surfsr, 0, 0, surf->zslice, surf->width, surf->height);
-	else
-		nvfx_resource_copy_region(pipe, surf->texture, surfsr, 0, 0, surf->zslice, &temp->base.base, tempsr, 0, 0, 0, surf->width, surf->height);
+	if(to_temp) {
+	        box.z = surf->u.tex.first_layer;
+		nvfx_resource_copy_region(pipe, &temp->base.base, 0, 0, 0, 0, surf->texture, surf->u.tex.level, &box);
+	}
+	else {
+		box.z = 0;
+		nvfx_resource_copy_region(pipe, surf->texture, surf->u.tex.level, 0, 0, surf->u.tex.first_layer, &temp->base.base, 0, &box);
+	}
 
 	/* If this triggers, it probably means we attempted to use the blitter
 	 * but failed due to non-renderability of the target.
diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c
index 7cb47a2..2debcb6 100644
--- a/src/gallium/drivers/nvfx/nvfx_transfer.c
+++ b/src/gallium/drivers/nvfx/nvfx_transfer.c
@@ -21,10 +21,10 @@
 
 struct pipe_transfer *
 nvfx_transfer_new(struct pipe_context *pipe,
-			  struct pipe_resource *pt,
-			  struct pipe_subresource sr,
-			  unsigned usage,
-			  const struct pipe_box *box)
+		  struct pipe_resource *pt,
+		  unsigned level,
+		  unsigned usage,
+		  const struct pipe_box *box)
 {
         if((usage & (PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_DONTBLOCK)) == PIPE_TRANSFER_DONTBLOCK)
         {
@@ -44,11 +44,11 @@
 			return NULL;
 
 		pipe_resource_reference(&tx->resource, pt);
-		tx->sr = sr;
+		tx->level = level;
 		tx->usage = usage;
 		tx->box = *box;
 
-		tx->slice_stride = tx->stride = util_format_get_stride(pt->format, box->width);
+		tx->layer_stride = tx->stride = util_format_get_stride(pt->format, box->width);
 		tx->data = buffer->data + util_format_get_stride(pt->format, box->x);
 
 		return tx;
@@ -62,20 +62,20 @@
 	        if(!tx)
 	        	return NULL;
 
-	        util_staging_transfer_init(pipe, pt, sr, usage, box, direct, &tx->base);
+	        util_staging_transfer_init(pipe, pt, level, usage, box, direct, &tx->base);
 
 		if(direct)
 		{
-			tx->base.base.stride = nvfx_subresource_pitch(pt, sr.level);
-			tx->base.base.slice_stride = tx->base.base.stride * u_minify(pt->height0, sr.level);
-			tx->offset = nvfx_subresource_offset(pt, sr.face, sr.level, box->z)
+			tx->base.base.stride = nvfx_subresource_pitch(pt, level);
+			tx->base.base.layer_stride = tx->base.base.stride * u_minify(pt->height0, level);
+			tx->offset = nvfx_subresource_offset(pt, box->z, level, box->z)
 				+ util_format_get_2d_size(pt->format, tx->base.base.stride, box->y)
 				+ util_format_get_stride(pt->format, box->x);
 		}
 		else
 		{
 			tx->base.base.stride = nvfx_subresource_pitch(tx->base.staging_resource, 0);
-			tx->base.base.slice_stride = tx->base.base.stride * tx->base.staging_resource->height0;
+			tx->base.base.layer_stride = tx->base.base.stride * tx->base.staging_resource->height0;
 			tx->offset = 0;
 		}
 
@@ -187,7 +187,7 @@
 
 static void nvfx_transfer_inline_write( struct pipe_context *pipe,
 				      struct pipe_resource *pr,
-				      struct pipe_subresource sr,
+				      unsigned level,
 				      unsigned usage,
 				      const struct pipe_box *box,
 				      const void *data,
@@ -196,7 +196,7 @@
 {
 	if(pr->target != PIPE_BUFFER)
 	{
-		u_default_transfer_inline_write(pipe, pr, sr, usage, box, data, stride, slice_stride);
+		u_default_transfer_inline_write(pipe, pr, level, usage, box, data, stride, slice_stride);
 	}
 	else
 	{
diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.h b/src/gallium/drivers/nvfx/nvfx_transfer.h
index 20f20d5..682f428 100644
--- a/src/gallium/drivers/nvfx/nvfx_transfer.h
+++ b/src/gallium/drivers/nvfx/nvfx_transfer.h
@@ -9,7 +9,7 @@
 struct pipe_transfer *
 nvfx_transfer_new(struct pipe_context *pcontext,
 			  struct pipe_resource *pt,
-			  struct pipe_subresource sr,
+			  unsigned level,
 			  unsigned usage,
 			  const struct pipe_box *box);
 
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 0ac4e4c..c02a692 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -186,11 +186,11 @@
             r300_depth_clear_value(fb->zsbuf->format, depth, stencil);
 
         r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG);
-        if (zstex->zmask_mem[fb->zsbuf->level]) {
+        if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) {
             r300->zmask_clear.dirty = TRUE;
             buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
         }
-        if (zstex->hiz_mem[fb->zsbuf->level])
+        if (zstex->hiz_mem[fb->zsbuf->u.tex.level])
             r300->hiz_clear.dirty = TRUE;
     }
 
@@ -259,8 +259,8 @@
      * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update
      * looks if zmask/hiz is in use and enables fastfill accordingly. */
     if (zstex &&
-        (zstex->zmask_in_use[fb->zsbuf->level] ||
-         zstex->hiz_in_use[fb->zsbuf->level])) {
+        (zstex->zmask_in_use[fb->zsbuf->u.tex.level] ||
+         zstex->hiz_in_use[fb->zsbuf->u.tex.level])) {
         r300->hyperz_state.dirty = TRUE;
     }
 }
@@ -300,58 +300,61 @@
 /* Flush a depth stencil buffer. */
 void r300_flush_depth_stencil(struct pipe_context *pipe,
                               struct pipe_resource *dst,
-                              struct pipe_subresource subdst,
-                              unsigned zslice)
+                              unsigned level,
+                              unsigned layer)
 {
     struct r300_context *r300 = r300_context(pipe);
-    struct pipe_surface *dstsurf;
+    struct pipe_surface *dstsurf, surf_tmpl;
     struct r300_texture *tex = r300_texture(dst);
 
-    if (!tex->zmask_mem[subdst.level])
+    if (!tex->zmask_mem[level])
         return;
-    if (!tex->zmask_in_use[subdst.level])
+    if (!tex->zmask_in_use[level])
         return;
 
-    dstsurf = pipe->screen->get_tex_surface(pipe->screen, dst,
-                                            subdst.face, subdst.level, zslice,
-                                            PIPE_BIND_DEPTH_STENCIL);
+    surf_tmpl.format = dst->format;
+    surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL;
+    surf_tmpl.u.tex.level = level;
+    surf_tmpl.u.tex.first_layer = layer;
+    surf_tmpl.u.tex.last_layer = layer;
+    dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
+
     r300->z_decomp_rd = TRUE;
     r300_blitter_begin(r300, R300_CLEAR_SURFACE);
     util_blitter_flush_depth_stencil(r300->blitter, dstsurf);
     r300_blitter_end(r300);
     r300->z_decomp_rd = FALSE;
 
-    tex->zmask_in_use[subdst.level] = FALSE;
+    tex->zmask_in_use[level] = FALSE;
 }
 
 /* Copy a block of pixels from one surface to another using HW. */
 static void r300_hw_copy_region(struct pipe_context* pipe,
                                 struct pipe_resource *dst,
-                                struct pipe_subresource subdst,
+                                unsigned dst_level,
                                 unsigned dstx, unsigned dsty, unsigned dstz,
                                 struct pipe_resource *src,
-                                struct pipe_subresource subsrc,
-                                unsigned srcx, unsigned srcy, unsigned srcz,
-                                unsigned width, unsigned height)
+                                unsigned src_level,
+                                const struct pipe_box *src_box)
 {
     struct r300_context* r300 = r300_context(pipe);
 
     r300_blitter_begin(r300, R300_COPY);
-    util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz,
-                             src, subsrc, srcx, srcy, srcz, width, height,
-                             TRUE);
+
+    /* Do a copy */
+    util_blitter_copy_region(r300->blitter, dst, dst_level, dstx, dsty, dstz,
+                             src, src_level, src_box, TRUE);
     r300_blitter_end(r300);
 }
 
 /* Copy a block of pixels from one surface to another. */
 static void r300_resource_copy_region(struct pipe_context *pipe,
                                       struct pipe_resource *dst,
-                                      struct pipe_subresource subdst,
+                                      unsigned dst_level,
                                       unsigned dstx, unsigned dsty, unsigned dstz,
                                       struct pipe_resource *src,
-                                      struct pipe_subresource subsrc,
-                                      unsigned srcx, unsigned srcy, unsigned srcz,
-                                      unsigned width, unsigned height)
+                                      unsigned src_level,
+                                      const struct pipe_box *src_box)
 {
     enum pipe_format old_format = dst->format;
     enum pipe_format new_format = old_format;
@@ -384,7 +387,7 @@
 
     is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
     if (is_depth) {
-        r300_flush_depth_stencil(pipe, src, subsrc, srcz);
+        r300_flush_depth_stencil(pipe, src, src_level, src_box->z);
     }
     if (old_format != new_format) {
         r300_texture_reinterpret_format(pipe->screen,
@@ -393,8 +396,8 @@
                                         src, new_format);
     }
 
-    r300_hw_copy_region(pipe, dst, subdst, dstx, dsty, dstz,
-                        src, subsrc, srcx, srcy, srcz, width, height);
+    r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
+                        src, src_level, src_box);
 
     if (old_format != new_format) {
         r300_texture_reinterpret_format(pipe->screen,
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index cd8f03d..2b97e4f 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -649,8 +649,8 @@
 /* r300_blit.c */
 void r300_flush_depth_stencil(struct pipe_context *pipe,
                               struct pipe_resource *dst,
-                              struct pipe_subresource subdst,
-                              unsigned zslice);
+                              unsigned level,
+                              unsigned layer);
 
 /* r300_query.c */
 void r300_resume_query(struct r300_context *r300,
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 5b6f82c..3e6852b 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -424,7 +424,7 @@
         if (can_hyperz) {
             uint32_t surf_pitch;
             struct r300_texture *tex;
-            int level = surf->base.level;
+            int level = surf->base.u.tex.level;
             tex = r300_texture(surf->base.texture);
 
             surf_pitch = surf->pitch & R300_DEPTHPITCH_MASK;
@@ -1073,8 +1073,8 @@
 
     tex = r300_texture(fb->zsbuf->texture);
 
-    offset = tex->hiz_mem[fb->zsbuf->level]->ofs;
-    stride = tex->desc.stride_in_pixels[fb->zsbuf->level];
+    offset = tex->hiz_mem[fb->zsbuf->u.tex.level]->ofs;
+    stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level];
 
     /* convert from pixels to 4x4 blocks */
     stride = ALIGN_DIVUP(stride, 4);
@@ -1096,7 +1096,7 @@
     z->current_func = -1;
 
     /* Mark the current zbuffer's hiz ram as in use. */
-    tex->hiz_in_use[fb->zsbuf->level] = TRUE;
+    tex->hiz_in_use[fb->zsbuf->u.tex.level] = TRUE;
 }
 
 void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state)
@@ -1110,9 +1110,9 @@
     int mult, offset_shift;
 
     tex = r300_texture(fb->zsbuf->texture);
-    stride = tex->desc.stride_in_pixels[fb->zsbuf->level];
+    stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level];
 
-    offset = tex->zmask_mem[fb->zsbuf->level]->ofs;
+    offset = tex->zmask_mem[fb->zsbuf->u.tex.level]->ofs;
 
     if (r300->z_compression == RV350_Z_COMPRESS_88)
         mult = 8;
@@ -1138,7 +1138,7 @@
     }
 
     /* Mark the current zbuffer's zmask as in use. */
-    tex->zmask_in_use[fb->zsbuf->level] = TRUE;
+    tex->zmask_in_use[fb->zsbuf->u.tex.level] = TRUE;
 }
 
 void r300_emit_ztop_state(struct r300_context* r300,
diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c
index 79f7f8a..5bf4cbe 100644
--- a/src/gallium/drivers/r300/r300_hyperz.c
+++ b/src/gallium/drivers/r300/r300_hyperz.c
@@ -158,8 +158,8 @@
     if (!r300->rws->get_value(r300->rws, R300_CAN_HYPERZ))
         return;
 
-    zmask_in_use = zstex->zmask_in_use[fb->zsbuf->level];
-    hiz_in_use = zstex->hiz_in_use[fb->zsbuf->level];
+    zmask_in_use = zstex->zmask_in_use[fb->zsbuf->u.tex.level];
+    hiz_in_use = zstex->hiz_in_use[fb->zsbuf->u.tex.level];
 
     /* Z fastfill. */
     if (zmask_in_use) {
@@ -333,7 +333,7 @@
 {
     struct r300_texture *tex;
     uint32_t zsize, ndw;
-    int level = surf->base.level;
+    int level = surf->base.u.tex.level;
 
     tex = r300_texture(surf->base.texture);
 
@@ -352,7 +352,7 @@
 {
     int bsize = 256;
     uint32_t zsize, ndw;
-    int level = surf->base.level;
+    int level = surf->base.u.tex.level;
     struct r300_texture *tex;
 
     tex = r300_texture(surf->base.texture);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 60700cf..2f8b6b8 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -1153,22 +1153,30 @@
 
 static void r300_resource_resolve(struct pipe_context* pipe,
                                   struct pipe_resource* dest,
-                                  struct pipe_subresource subdest,
+                                  unsigned dst_layer,
                                   struct pipe_resource* src,
-                                  struct pipe_subresource subsrc)
+                                  unsigned src_layer)
 {
     struct r300_context* r300 = r300_context(pipe);
+    struct pipe_surface* srcsurf, surf_tmpl;
     struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
-    struct pipe_surface* srcsurf = src->screen->get_tex_surface(src->screen,
-            src, subsrc.face, subsrc.level, 0, 0);
     float color[] = {0, 0, 0, 0};
 
+    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+    surf_tmpl.format = src->format;
+    surf_tmpl.usage = 0; /* not really a surface hence no bind flags */
+    surf_tmpl.u.tex.level = 0; /* msaa resources cannot have mipmaps */
+    surf_tmpl.u.tex.first_layer = src_layer;
+    surf_tmpl.u.tex.last_layer = src_layer;
+    srcsurf = pipe->create_surface(pipe, src, &surf_tmpl);
+    surf_tmpl.format = dest->format;
+    surf_tmpl.u.tex.first_layer = dst_layer;
+    surf_tmpl.u.tex.last_layer = dst_layer;
+
     DBG(r300, DBG_DRAW, "r300: Resolving resource...\n");
 
     /* Enable AA resolve. */
-    aa->dest = r300_surface(
-            dest->screen->get_tex_surface(dest->screen, dest, subdest.face,
-                                          subdest.level, 0, 0));
+    aa->dest = r300_surface(pipe->create_surface(pipe, dest, &surf_tmpl));
 
     aa->aaresolve_ctl =
         R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE |
diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c
index f6f3302..dd1df97 100644
--- a/src/gallium/drivers/r300/r300_resource.c
+++ b/src/gallium/drivers/r300/r300_resource.c
@@ -58,6 +58,8 @@
    r300->context.transfer_destroy = u_transfer_destroy_vtbl;
    r300->context.transfer_inline_write = u_transfer_inline_write_vtbl;
    r300->context.is_resource_referenced = u_is_resource_referenced_vtbl;
+   r300->context.create_surface = r300_create_surface;
+   r300->context.surface_destroy = r300_surface_destroy;
 }
 
 void r300_init_screen_resource_functions(struct r300_screen *r300screen)
@@ -67,7 +69,4 @@
    r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl;
    r300screen->screen.resource_destroy = u_resource_destroy_vtbl;
    r300screen->screen.user_buffer_create = r300_user_buffer_create;
-
-   r300screen->screen.get_tex_surface = r300_get_tex_surface;
-   r300screen->screen.tex_surface_destroy = r300_tex_surface_destroy;
 }
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
index 6a0142f..98d36ad 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.c
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -51,7 +51,7 @@
 
 static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context,
                                                 struct pipe_resource *buf,
-                                                unsigned face, unsigned level)
+                                                unsigned level, int layer)
 {
     return r300_buffer_is_referenced(context, buf, R300_REF_CS);
 }
@@ -142,7 +142,7 @@
 static struct pipe_transfer*
 r300_default_get_transfer(struct pipe_context *context,
                           struct pipe_resource *resource,
-                          struct pipe_subresource sr,
+                          unsigned level,
                           unsigned usage,
                           const struct pipe_box *box)
 {
@@ -151,11 +151,11 @@
          util_slab_alloc(&r300->pool_transfers);
 
    transfer->resource = resource;
-   transfer->sr = sr;
+   transfer->level = level;
    transfer->usage = usage;
    transfer->box = *box;
    transfer->stride = 0;
-   transfer->slice_stride = 0;
+   transfer->layer_stride = 0;
    transfer->data = NULL;
 
    /* Note strides are zero, this is ok for buffers, but not for
@@ -341,6 +341,7 @@
     rbuf->b.b.width0 = bytes;
     rbuf->b.b.height0 = 1;
     rbuf->b.b.depth0 = 1;
+    rbuf->b.b.array_size = 1;
     rbuf->b.b.flags = 0;
     rbuf->domain = R300_DOMAIN_GTT;
     rbuf->num_ranges = 0;
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 405b059..0f56370 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -647,12 +647,12 @@
     for (i = 0; i < state->nr_cbufs; i++) {
         r300_tex_set_tiling_flags(r300,
                                   r300_texture(state->cbufs[i]->texture),
-                                  state->cbufs[i]->level);
+                                  state->cbufs[i]->u.tex.level);
     }
     if (state->zsbuf) {
         r300_tex_set_tiling_flags(r300,
                                   r300_texture(state->zsbuf->texture),
-                                  state->zsbuf->level);
+                                  state->zsbuf->u.tex.level);
     }
 }
 
@@ -663,14 +663,14 @@
     struct r300_texture *rtex = r300_texture(tex);
 
     fprintf(stderr,
-            "r300:   %s[%i] Dim: %ix%i, Offset: %i, ZSlice: %i, "
-            "Face: %i, Level: %i, Format: %s\n"
+            "r300:   %s[%i] Dim: %ix%i, Firstlayer: %i, "
+            "Lastlayer: %i, Level: %i, Format: %s\n"
 
             "r300:     TEX: Macro: %s, Micro: %s, Pitch: %i, "
             "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
 
-            binding, index, surf->width, surf->height, surf->offset,
-            surf->zslice, surf->face, surf->level,
+            binding, index, surf->width, surf->height,
+            surf->u.tex.first_layer, surf->u.tex.last_layer, surf->u.tex.level,
             util_format_short_name(surf->format),
 
             rtex->desc.macrotile[0] ? "YES" : " NO",
@@ -768,7 +768,7 @@
             struct r300_surface *zs_surf = r300_surface(state->zsbuf);
             struct r300_texture *tex;
             int compress = r300->screen->caps.is_rv350 ? RV350_Z_COMPRESS_88 : R300_Z_COMPRESS_44;
-            int level = zs_surf->base.level;
+            int level = zs_surf->base.u.tex.level;
 
             tex = r300_texture(zs_surf->base.texture);
 
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index dc2d9ec..a6d0776 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -721,9 +721,9 @@
                                       r300->screen->caps.is_r500);
 
             /* determine min/max levels */
-            max_level = MIN3(sampler->max_lod + view->base.first_level,
-                             tex->desc.b.b.last_level, view->base.last_level);
-            min_level = MIN2(sampler->min_lod + view->base.first_level,
+            max_level = MIN3(sampler->max_lod + view->base.u.tex.first_level,
+                             tex->desc.b.b.last_level, view->base.u.tex.last_level);
+            min_level = MIN2(sampler->min_lod + view->base.u.tex.first_level,
                              max_level);
 
             if (tex->desc.is_npot && min_level > 0) {
@@ -887,9 +887,8 @@
             for (level = 0; level <= tex->last_level; level++)
                 if (r300_texture(tex)->zmask_in_use[level]) {
                     /* We don't handle 3D textures and cubemaps yet. */
-                    r300_flush_depth_stencil(&r300->context, tex,
-                                             u_subresource(0, level), 0);
-                }
+                    r300_flush_depth_stencil(&r300->context, tex, level, 0);
+                 }
         }
 }
 
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 6c14e94..4b7b3e0 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -668,8 +668,8 @@
 }
 
 static unsigned r300_texture_is_referenced(struct pipe_context *context,
-					 struct pipe_resource *texture,
-					 unsigned face, unsigned level)
+                                           struct pipe_resource *texture,
+                                           unsigned level, int layer)
 {
     struct r300_context *r300 = r300_context(context);
     struct r300_texture *rtex = (struct r300_texture *)texture;
@@ -682,7 +682,7 @@
 }
 
 static void r300_texture_destroy(struct pipe_screen *screen,
-				 struct pipe_resource* texture)
+                                 struct pipe_resource* texture)
 {
     struct r300_texture* tex = (struct r300_texture*)texture;
     struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys;
@@ -851,28 +851,29 @@
 
 /* Not required to implement u_resource_vtbl, consider moving to another file:
  */
-struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
-                                          struct pipe_resource* texture,
-					  unsigned face,
-					  unsigned level,
-					  unsigned zslice,
-					  unsigned flags)
+struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
+                                         struct pipe_resource* texture,
+                                         const struct pipe_surface *surf_tmpl)
 {
     struct r300_texture* tex = r300_texture(texture);
     struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
+    unsigned level = surf_tmpl->u.tex.level;
+
+    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
 
     if (surface) {
         uint32_t offset, tile_height;
 
         pipe_reference_init(&surface->base.reference, 1);
         pipe_resource_reference(&surface->base.texture, texture);
-        surface->base.format = texture->format;
+        surface->base.context = ctx;
+        surface->base.format = surf_tmpl->format;
         surface->base.width = u_minify(texture->width0, level);
         surface->base.height = u_minify(texture->height0, level);
-        surface->base.usage = flags;
-        surface->base.zslice = zslice;
-        surface->base.face = face;
-        surface->base.level = level;
+        surface->base.usage = surf_tmpl->usage;
+        surface->base.u.tex.level = level;
+        surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+        surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
 
         surface->buffer = tex->buffer;
 
@@ -881,8 +882,8 @@
         if (surface->domain & R300_DOMAIN_VRAM)
             surface->domain &= ~R300_DOMAIN_GTT;
 
-        surface->offset = r300_texture_get_offset(&tex->desc,
-                                                  level, zslice, face);
+        surface->offset = r300_texture_get_offset(&tex->desc, level,
+                                                  surf_tmpl->u.tex.first_layer);
         surface->pitch = tex->fb_state.pitch[level];
         surface->format = tex->fb_state.format;
 
@@ -913,13 +914,13 @@
         else
             surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z;
 
-        SCREEN_DBG(r300_screen(screen), DBG_CBZB,
-                   "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",
-                   surface->cbzb_allowed ? "YES" : " NO",
-                   surface->cbzb_width, surface->cbzb_height,
-                   offset & 2047,
-                   tex->desc.microtile ? "YES" : " NO",
-                   tex->desc.macrotile[level] ? "YES" : " NO");
+        DBG(r300_context(ctx), DBG_CBZB,
+            "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n",
+            surface->cbzb_allowed ? "YES" : " NO",
+            surface->cbzb_width, surface->cbzb_height,
+            offset & 2047,
+            tex->desc.microtile ? "YES" : " NO",
+            tex->desc.macrotile[level] ? "YES" : " NO");
     }
 
     return &surface->base;
@@ -927,7 +928,7 @@
 
 /* Not required to implement u_resource_vtbl, consider moving to another file:
  */
-void r300_tex_surface_destroy(struct pipe_surface* s)
+void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s)
 {
     pipe_resource_reference(&s->texture, NULL);
     FREE(s);
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index fe9d351..0ab22f7 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -27,6 +27,7 @@
 #include "pipe/p_format.h"
 
 struct pipe_screen;
+struct pipe_context;
 struct pipe_resource;
 struct winsys_handle;
 struct r300_texture_format_state;
@@ -70,13 +71,10 @@
 		    const struct pipe_resource* templ);
 
 
-struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
-					  struct pipe_resource* texture,
-					  unsigned face,
-					  unsigned level,
-					  unsigned zslice,
-					  unsigned flags);
+struct pipe_surface* r300_create_surface(struct pipe_context *ctx,
+                                         struct pipe_resource* texture,
+                                         const struct pipe_surface *surf_tmpl);
 
-void r300_tex_surface_destroy(struct pipe_surface* s);
+void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s);
 
 #endif /* R300_TEXTURE_H */
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index 543d0fd..8c98594 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -474,22 +474,16 @@
 }
 
 unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
-                                 unsigned level, unsigned zslice,
-                                 unsigned face)
+                                 unsigned level, unsigned layer)
 {
     unsigned offset = desc->offset_in_bytes[level];
 
     switch (desc->b.b.target) {
         case PIPE_TEXTURE_3D:
-            assert(face == 0);
-            return offset + zslice * desc->layer_size_in_bytes[level];
-
-        case PIPE_TEXTURE_CUBE:
-            assert(zslice == 0);
-            return offset + face * desc->layer_size_in_bytes[level];
+            return offset + layer * desc->layer_size_in_bytes[level];
 
         default:
-            assert(zslice == 0 && face == 0);
+            assert(layer == 0);
             return offset;
     }
 }
diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h
index 3d7fe1f..44d88794 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.h
+++ b/src/gallium/drivers/r300/r300_texture_desc.h
@@ -52,7 +52,6 @@
                                unsigned max_buffer_size);
 
 unsigned r300_texture_get_offset(struct r300_texture_desc *desc,
-                                 unsigned level, unsigned zslice,
-                                 unsigned face);
+                                 unsigned level, unsigned layer);
 
 #endif
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index e9333b3..755aff8 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -27,6 +27,7 @@
 
 #include "util/u_memory.h"
 #include "util/u_format.h"
+#include "util/u_box.h"
 
 struct r300_transfer {
     /* Parent class */
@@ -52,16 +53,10 @@
 {
     struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
     struct pipe_resource *tex = transfer->resource;
-    struct pipe_subresource subdst;
 
-    subdst.face = 0;
-    subdst.level = 0;
-
-    ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, subdst,
-			      0, 0, 0,
-			      tex, transfer->sr,
-			      transfer->box.x, transfer->box.y, transfer->box.z,
-			      transfer->box.width, transfer->box.height);
+    ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, 0,
+                              0, 0, 0,
+                              tex, transfer->level, &transfer->box);
 }
 
 /* Copy a detiled texture to a tiled one. */
@@ -70,26 +65,22 @@
 {
     struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer;
     struct pipe_resource *tex = transfer->resource;
-    struct pipe_subresource subsrc;
+    struct pipe_box src_box;
+    u_box_origin_2d(transfer->box.width, transfer->box.height, &src_box);
 
-    subsrc.face = 0;
-    subsrc.level = 0;
-
-    ctx->resource_copy_region(ctx, tex, transfer->sr,
-			      transfer->box.x, transfer->box.y, transfer->box.z,
-                              &r300transfer->linear_texture->desc.b.b, subsrc,
-			      0, 0, 0,
-			      transfer->box.width, transfer->box.height);
+    ctx->resource_copy_region(ctx, tex, transfer->level,
+                              transfer->box.x, transfer->box.y, transfer->box.z,
+                              &r300transfer->linear_texture->desc.b.b, 0, &src_box);
 
     ctx->flush(ctx, 0, NULL);
 }
 
 struct pipe_transfer*
 r300_texture_get_transfer(struct pipe_context *ctx,
-			  struct pipe_resource *texture,
-			  struct pipe_subresource sr,
-			  unsigned usage,
-			  const struct pipe_box *box)
+                          struct pipe_resource *texture,
+                          unsigned level,
+                          unsigned usage,
+                          const struct pipe_box *box)
 {
     struct r300_context *r300 = r300_context(ctx);
     struct r300_texture *tex = r300_texture(texture);
@@ -116,25 +107,27 @@
     if (trans) {
         /* Initialize the transfer object. */
         pipe_resource_reference(&trans->transfer.resource, texture);
-        trans->transfer.sr = sr;
+        trans->transfer.level = level;
         trans->transfer.usage = usage;
         trans->transfer.box = *box;
 
         /* If the texture is tiled, we must create a temporary detiled texture
          * for this transfer.
          * Also make write transfers pipelined. */
-        if (tex->desc.microtile || tex->desc.macrotile[sr.level] ||
+        if (tex->desc.microtile || tex->desc.macrotile[level] ||
             ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) {
             base.target = PIPE_TEXTURE_2D;
             base.format = texture->format;
             base.width0 = box->width;
             base.height0 = box->height;
-            base.depth0 = 0;
+            /* XXX: was depth0 = 0 */
+            base.depth0 = 1;
+            base.array_size = 1;
             base.last_level = 0;
             base.nr_samples = 0;
             base.usage = PIPE_USAGE_DYNAMIC;
             base.bind = 0;
-	    base.flags = R300_RESOURCE_FLAG_TRANSFER;
+            base.flags = R300_RESOURCE_FLAG_TRANSFER;
 
             /* For texture reading, the temporary (detiled) texture is used as
              * a render target when blitting from a tiled texture. */
@@ -164,7 +157,7 @@
                 if (!trans->linear_texture) {
                     /* For linear textures, it's safe to fallback to
                      * an unpipelined transfer. */
-                    if (!tex->desc.microtile && !tex->desc.macrotile[sr.level]) {
+                    if (!tex->desc.microtile && !tex->desc.macrotile[level]) {
                         goto unpipelined;
                     }
 
@@ -182,7 +175,7 @@
             /* Set the stride.
 	     *
 	     * Even though we are using an internal texture for this,
-	     * the transfer sr, box and usage parameters still reflect
+	     * the transfer level, box and usage parameters still reflect
 	     * the arguments received to get_transfer.  We just do the
 	     * right thing internally.
 	     */
@@ -202,9 +195,8 @@
 
     unpipelined:
         /* Unpipelined transfer. */
-        trans->transfer.stride = tex->desc.stride_in_bytes[sr.level];
-        trans->offset = r300_texture_get_offset(&tex->desc,
-                                                sr.level, box->z, sr.face);
+        trans->transfer.stride = tex->desc.stride_in_bytes[level];
+        trans->offset = r300_texture_get_offset(&tex->desc, level, box->z);
 
         if (referenced_cs)
             ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h
index 0d32a68..7977ef5 100644
--- a/src/gallium/drivers/r300/r300_transfer.h
+++ b/src/gallium/drivers/r300/r300_transfer.h
@@ -30,22 +30,22 @@
 
 struct pipe_transfer*
 r300_texture_get_transfer(struct pipe_context *ctx,
-			  struct pipe_resource *texture,
-			  struct pipe_subresource sr,
-			  unsigned usage,
-			  const struct pipe_box *box);
+                          struct pipe_resource *texture,
+                          unsigned level,
+                          unsigned usage,
+                          const struct pipe_box *box);
 
 void
 r300_texture_transfer_destroy(struct pipe_context *ctx,
-			      struct pipe_transfer *trans);
+                              struct pipe_transfer *trans);
 
 void*
 r300_texture_transfer_map(struct pipe_context *ctx,
-			  struct pipe_transfer *transfer);
+                          struct pipe_transfer *transfer);
 
 void
 r300_texture_transfer_unmap(struct pipe_context *ctx,
-			    struct pipe_transfer *transfer);
+                            struct pipe_transfer *transfer);
 
 
 #endif
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 0509522..bee6752 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -410,9 +410,9 @@
 	r600_pipe_state_add_reg(rstate, R_030010_RESOURCE0_WORD4,
 				word4 | S_030010_NUM_FORMAT_ALL(V_030010_SQ_NUM_FORMAT_NORM) |
 				S_030010_SRF_MODE_ALL(V_030010_SFR_MODE_NO_ZERO) |
-				S_030010_BASE_LEVEL(state->first_level), 0xFFFFFFFF, NULL);
+				S_030010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_030014_RESOURCE0_WORD5,
-				S_030014_LAST_LEVEL(state->last_level) |
+				S_030014_LAST_LEVEL(state->u.tex.last_level) |
 				S_030014_BASE_ARRAY(0) |
 				S_030014_LAST_ARRAY(0), 0xffffffff, NULL);
 	r600_pipe_state_add_reg(rstate, R_030018_RESOURCE0_WORD6, 0x0, 0xFFFFFFFF, NULL);
@@ -633,10 +633,11 @@
 	struct r600_resource_texture *rtex;
 	struct r600_resource *rbuffer;
 	struct r600_surface *surf;
-	unsigned level = state->cbufs[cb]->level;
+	unsigned level = state->cbufs[cb]->u.tex.level;
 	unsigned pitch, slice;
 	unsigned color_info;
 	unsigned format, swap, ntype;
+	unsigned offset;
 	const struct util_format_description *desc;
 	struct r600_bo *bo[3];
 
@@ -647,6 +648,9 @@
 	bo[1] = rbuffer->bo;
 	bo[2] = rbuffer->bo;
 
+	/* XXX quite sure for dx10+ hw don't need any offset hacks */
+	offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture,
+					 level, state->cbufs[cb]->u.tex.first_layer);
 	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
 	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
 	ntype = 0;
@@ -666,7 +670,7 @@
 	/* FIXME handle enabling of CB beyond BASE8 which has different offset */
 	r600_pipe_state_add_reg(rstate,
 				R_028C60_CB_COLOR0_BASE + cb * 0x3C,
-				(state->cbufs[cb]->offset +  r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]);
+				(offset +  r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]);
 	r600_pipe_state_add_reg(rstate,
 				R_028C78_CB_COLOR0_DIM + cb * 0x3C,
 				0x0, 0xFFFFFFFF, NULL);
@@ -698,11 +702,12 @@
 	struct r600_surface *surf;
 	unsigned level;
 	unsigned pitch, slice, format, stencil_format;
+	unsigned offset;
 
 	if (state->zsbuf == NULL)
 		return;
 
-	level = state->zsbuf->level;
+	level = state->zsbuf->u.tex.level;
 
 	surf = (struct r600_surface *)state->zsbuf;
 	rtex = (struct r600_resource_texture*)state->zsbuf->texture;
@@ -712,24 +717,27 @@
 	rtex->depth = 1;
 	rbuffer = &rtex->resource;
 
+	/* XXX quite sure for dx10+ hw don't need any offset hacks */
+	offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
+					 level, state->zsbuf->u.tex.first_layer);
 	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
 	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
 	format = r600_translate_dbformat(state->zsbuf->texture->format);
 	stencil_format = r600_translate_stencilformat(state->zsbuf->texture->format);
 
 	r600_pipe_state_add_reg(rstate, R_028048_DB_Z_READ_BASE,
-				(state->zsbuf->offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
+				(offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
 	r600_pipe_state_add_reg(rstate, R_028050_DB_Z_WRITE_BASE,
-				(state->zsbuf->offset  + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
+				(offset  + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
 
 	if (stencil_format) {
 		uint32_t stencil_offset;
 
 		stencil_offset = ((surf->aligned_height * rtex->pitch_in_bytes[level]) + 255) & ~255;
 		r600_pipe_state_add_reg(rstate, R_02804C_DB_STENCIL_READ_BASE,
-					(state->zsbuf->offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
+					(offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
 		r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE,
-					(state->zsbuf->offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
+					(offset + stencil_offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
 	}
 
 	r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, 0x00000000, 0xFFFFFFFF, NULL);
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 74cf968..f35eacd 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -81,16 +81,21 @@
 int r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture)
 {
 	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
-	struct pipe_surface *zsurf, *cbsurf;
+	struct pipe_surface *zsurf, *cbsurf, surf_tmpl;
 	int level = 0;
 	float depth = 1.0f;
+	surf_tmpl.format = texture->resource.base.b.format;
+	surf_tmpl.u.tex.level = level;
+	surf_tmpl.u.tex.first_layer = 0;
+	surf_tmpl.u.tex.last_layer = 0;
+	surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL;
 
-	zsurf = ctx->screen->get_tex_surface(ctx->screen, &texture->resource.base.b, 0, level, 0,
-					     PIPE_BIND_DEPTH_STENCIL);
+	zsurf = ctx->create_surface(ctx, &texture->resource.base.b, &surf_tmpl);
 
-	cbsurf = ctx->screen->get_tex_surface(ctx->screen,
-			(struct pipe_resource*)texture->flushed_depth_texture,
-			0, level, 0, PIPE_BIND_RENDER_TARGET);
+	surf_tmpl.format = ((struct pipe_resource*)texture->flushed_depth_texture)->format;
+	surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+	cbsurf = ctx->create_surface(ctx,
+			(struct pipe_resource*)texture->flushed_depth_texture, &surf_tmpl);
 
 	if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 ||
 	    rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635)
@@ -155,40 +160,37 @@
 /* Copy a block of pixels from one surface to another using HW. */
 static void r600_hw_copy_region(struct pipe_context *ctx,
                                 struct pipe_resource *dst,
-                                struct pipe_subresource subdst,
+                                unsigned dst_level,
                                 unsigned dstx, unsigned dsty, unsigned dstz,
                                 struct pipe_resource *src,
-                                struct pipe_subresource subsrc,
-                                unsigned srcx, unsigned srcy, unsigned srcz,
-                                unsigned width, unsigned height)
+                                unsigned src_level,
+                                const struct pipe_box *src_box)
 {
 	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
 
 	r600_blitter_begin(ctx, R600_COPY);
-	util_blitter_copy_region(rctx->blitter, dst, subdst, dstx, dsty, dstz,
-				 src, subsrc, srcx, srcy, srcz, width, height,
-				 TRUE);
+	util_blitter_copy_region(rctx->blitter, dst, dst_level, dstx, dsty, dstz,
+				 src, src_level, src_box, TRUE);
 	r600_blitter_end(ctx);
 }
 
 static void r600_resource_copy_region(struct pipe_context *ctx,
 				      struct pipe_resource *dst,
-				      struct pipe_subresource subdst,
+				      unsigned dst_level,
 				      unsigned dstx, unsigned dsty, unsigned dstz,
 				      struct pipe_resource *src,
-				      struct pipe_subresource subsrc,
-				      unsigned srcx, unsigned srcy, unsigned srcz,
-				      unsigned width, unsigned height)
+				      unsigned src_level,
+				      const struct pipe_box *src_box)
 {
 	boolean is_depth;
 	/* there is something wrong with depth resource copies at the moment so avoid them for now */
 	is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
 	if (is_depth)
-		util_resource_copy_region(ctx, dst, subdst, dstx, dsty, dstz,
-					  src, subsrc, srcx, srcy, srcz, width, height);
+		util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
+					  src, src_level, src_box);
 	else
-		r600_hw_copy_region(ctx, dst, subdst, dstx, dsty, dstz,
-				    src, subsrc, srcx, srcy, srcz, width, height);
+		r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
+				    src, src_level, src_box);
 }
 
 void r600_init_blit_functions(struct r600_pipe_context *rctx)
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index a432271..76f9d88 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -89,6 +89,7 @@
 	rbuffer->r.base.b.width0 = bytes;
 	rbuffer->r.base.b.height0 = 1;
 	rbuffer->r.base.b.depth0 = 1;
+	rbuffer->r.base.b.array_size = 1;
 	rbuffer->r.base.b.flags = 0;
 	rbuffer->num_ranges = 0;
 	rbuffer->r.bo = NULL;
@@ -188,7 +189,7 @@
 
 unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
 					 struct pipe_resource *buf,
-					 unsigned face, unsigned level)
+					 unsigned level, int layer)
 {
 	/* FIXME */
 	return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 511e52f..e7776a0 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -120,6 +120,7 @@
 	r600_init_blit_functions(rctx);
 	r600_init_query_functions(rctx);
 	r600_init_context_resource_functions(rctx);
+	r600_init_surface_functions(rctx);
 
 	switch (r600_get_family(rctx->radeon)) {
 	case CHIP_R600:
@@ -467,7 +468,6 @@
 	rscreen->screen.get_paramf = r600_get_paramf;
 	rscreen->screen.is_format_supported = r600_is_format_supported;
 	rscreen->screen.context_create = r600_create_context;
-	r600_init_screen_texture_functions(&rscreen->screen);
 	r600_init_screen_resource_functions(&rscreen->screen);
 
 	rscreen->tiling_info = r600_get_tiling_info(radeon);
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index ba9fedf..835aa33 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -194,7 +194,7 @@
 					      unsigned bind);
 unsigned r600_buffer_is_referenced_by_cs(struct pipe_context *context,
 					 struct pipe_resource *buf,
-					 unsigned face, unsigned level);
+					 unsigned level, int layer);
 struct pipe_resource *r600_buffer_from_handle(struct pipe_screen *screen,
 					      struct winsys_handle *whandle);
 int r600_upload_index_buffer(struct r600_pipe_context *rctx, struct r600_drawl *draw);
@@ -223,9 +223,12 @@
 
 /* r600_texture.c */
 void r600_init_screen_texture_functions(struct pipe_screen *screen);
+void r600_init_surface_functions(struct r600_pipe_context *r600);
 uint32_t r600_translate_texformat(enum pipe_format format,
 				  const unsigned char *swizzle_view, 
 				  uint32_t *word4_p, uint32_t *yuv_format_p);
+unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
+					unsigned level, unsigned layer);
 
 /* r600_translate.c */
 void r600_begin_vertex_translate(struct r600_pipe_context *rctx);
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index 7a2d1f4..25aa846 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -112,7 +112,7 @@
 /* r600_texture.c texture transfer functions. */
 struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
 						struct pipe_resource *texture,
-						struct pipe_subresource sr,
+						unsigned level,
 						unsigned usage,
 						const struct pipe_box *box);
 void r600_texture_transfer_destroy(struct pipe_context *ctx,
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index bf4ca05..cd089e8 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -603,9 +603,9 @@
 				word4 | S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_NORM) |
 				S_038010_SRF_MODE_ALL(V_038010_SFR_MODE_NO_ZERO) |
 				S_038010_REQUEST_SIZE(1) |
-				S_038010_BASE_LEVEL(state->first_level), 0xFFFFFFFF, NULL);
+				S_038010_BASE_LEVEL(state->u.tex.first_level), 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_038014_RESOURCE0_WORD5,
-				S_038014_LAST_LEVEL(state->last_level) |
+				S_038014_LAST_LEVEL(state->u.tex.last_level) |
 				S_038014_BASE_ARRAY(0) |
 				S_038014_LAST_ARRAY(0), 0xFFFFFFFF, NULL);
 	r600_pipe_state_add_reg(rstate, R_038018_RESOURCE0_WORD6,
@@ -824,10 +824,11 @@
 	struct r600_resource_texture *rtex;
 	struct r600_resource *rbuffer;
 	struct r600_surface *surf;
-	unsigned level = state->cbufs[cb]->level;
+	unsigned level = state->cbufs[cb]->u.tex.level;
 	unsigned pitch, slice;
 	unsigned color_info;
 	unsigned format, swap, ntype;
+	unsigned offset;
 	const struct util_format_description *desc;
 	struct r600_bo *bo[3];
 
@@ -838,6 +839,9 @@
 	bo[1] = rbuffer->bo;
 	bo[2] = rbuffer->bo;
 
+	/* XXX quite sure for dx10+ hw don't need any offset hacks */
+	offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture,
+					 level, state->cbufs[cb]->u.tex.first_layer);
 	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
 	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
 	ntype = 0;
@@ -857,7 +861,7 @@
 
 	r600_pipe_state_add_reg(rstate,
 				R_028040_CB_COLOR0_BASE + cb * 4,
-				(state->cbufs[cb]->offset + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]);
+				(offset + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]);
 	r600_pipe_state_add_reg(rstate,
 				R_0280A0_CB_COLOR0_INFO + cb * 4,
 				color_info, 0xFFFFFFFF, bo[0]);
@@ -888,11 +892,12 @@
 	struct r600_surface *surf;
 	unsigned level;
 	unsigned pitch, slice, format;
+	unsigned offset;
 
 	if (state->zsbuf == NULL)
 		return;
 
-	level = state->zsbuf->level;
+	level = state->zsbuf->u.tex.level;
 
 	surf = (struct r600_surface *)state->zsbuf;
 	rtex = (struct r600_resource_texture*)state->zsbuf->texture;
@@ -902,12 +907,15 @@
 	rtex->depth = 1;
 	rbuffer = &rtex->resource;
 
+	/* XXX quite sure for dx10+ hw don't need any offset hacks */
+	offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
+					 level, state->zsbuf->u.tex.first_layer);
 	pitch = rtex->pitch_in_pixels[level] / 8 - 1;
 	slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
 	format = r600_translate_dbformat(state->zsbuf->texture->format);
 
 	r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE,
-				(state->zsbuf->offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
+				(offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo);
 	r600_pipe_state_add_reg(rstate, R_028000_DB_DEPTH_SIZE,
 				S_028000_PITCH_TILE_MAX(pitch) | S_028000_SLICE_TILE_MAX(slice),
 				0xFFFFFFFF, NULL);
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index 8ecd434..5938d7e 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -45,14 +45,10 @@
 {
 	struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
 	struct pipe_resource *texture = transfer->resource;
-	struct pipe_subresource subdst;
 
-	subdst.face = 0;
-	subdst.level = 0;
 	ctx->resource_copy_region(ctx, rtransfer->staging_texture,
-				subdst, 0, 0, 0, texture, transfer->sr,
-				transfer->box.x, transfer->box.y, transfer->box.z,
-				transfer->box.width, transfer->box.height);
+				0, 0, 0, 0, texture, transfer->level,
+				&transfer->box);
 }
 
 
@@ -61,34 +57,32 @@
 {
 	struct pipe_transfer *transfer = (struct pipe_transfer*)rtransfer;
 	struct pipe_resource *texture = transfer->resource;
-	struct pipe_subresource subsrc;
+	struct pipe_box sbox;
 
-	subsrc.face = 0;
-	subsrc.level = 0;
-	ctx->resource_copy_region(ctx, texture, transfer->sr,
+	sbox.x = sbox.y = sbox.z = 0;
+	sbox.width = transfer->box.width;
+	sbox.height = transfer->box.height;
+	/* XXX that might be wrong */
+	sbox.depth = 1;
+	ctx->resource_copy_region(ctx, texture, transfer->level,
 				  transfer->box.x, transfer->box.y, transfer->box.z,
-				  rtransfer->staging_texture, subsrc,
-				  0, 0, 0,
-				  transfer->box.width, transfer->box.height);
+				  rtransfer->staging_texture,
+				  0, &sbox);
 
 	ctx->flush(ctx, 0, NULL);
 }
 
-static unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
-					unsigned level, unsigned zslice,
-					unsigned face)
+unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
+					unsigned level, unsigned layer)
 {
 	unsigned offset = rtex->offset[level];
 
 	switch (rtex->resource.base.b.target) {
 	case PIPE_TEXTURE_3D:
-		assert(face == 0);
-		return offset + zslice * rtex->layer_size[level];
 	case PIPE_TEXTURE_CUBE:
-		assert(zslice == 0);
-		return offset + face * rtex->layer_size[level];
+		return offset + layer * rtex->layer_size[level];
 	default:
-		assert(zslice == 0 && face == 0);
+		assert(layer == 0);
 		return offset;
 	}
 }
@@ -175,7 +169,6 @@
 					struct r600_resource_texture *rtex,
 					unsigned level)
 {
-	struct r600_screen* rscreen = (struct r600_screen *)screen;
 	struct pipe_resource *ptex = &rtex->resource.base.b;
 	struct radeon *radeon = (struct radeon *)screen->winsys;
 	enum chip_class chipc = r600_get_family_class(radeon);
@@ -382,36 +375,39 @@
 			rtex->pitch_in_bytes[0], whandle);
 }
 
-static struct pipe_surface *r600_get_tex_surface(struct pipe_screen *screen,
+static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
 						struct pipe_resource *texture,
-						unsigned face, unsigned level,
-						unsigned zslice, unsigned flags)
+						const struct pipe_surface *surf_tmpl)
 {
 	struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture;
 	struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
-	unsigned offset, tile_height;
+	unsigned tile_height;
+	unsigned level = surf_tmpl->u.tex.level;
 
+	assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
 	if (surface == NULL)
 		return NULL;
-	offset = r600_texture_get_offset(rtex, level, zslice, face);
+        /* XXX no offset */
+/*	offset = r600_texture_get_offset(rtex, level, surf_tmpl->u.tex.first_layer);*/
 	pipe_reference_init(&surface->base.reference, 1);
 	pipe_resource_reference(&surface->base.texture, texture);
-	surface->base.format = texture->format;
+	surface->base.context = pipe;
+	surface->base.format = surf_tmpl->format;
 	surface->base.width = mip_minify(texture->width0, level);
 	surface->base.height = mip_minify(texture->height0, level);
-	surface->base.offset = offset;
-	surface->base.usage = flags;
-	surface->base.zslice = zslice;
+	surface->base.usage = surf_tmpl->usage;
 	surface->base.texture = texture;
-	surface->base.face = face;
-	surface->base.level = level;
+	surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+	surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
+	surface->base.u.tex.level = level;
 
-	tile_height = r600_get_height_alignment(screen, rtex->array_mode[level]);
+	tile_height = r600_get_height_alignment(pipe->screen, rtex->array_mode[level]);
 	surface->aligned_height = align(surface->base.height, tile_height);
 	return &surface->base;
 }
 
-static void r600_tex_surface_destroy(struct pipe_surface *surface)
+static void r600_surface_destroy(struct pipe_context *pipe,
+				 struct pipe_surface *surface)
 {
 	pipe_resource_reference(&surface->texture, NULL);
 	FREE(surface);
@@ -444,7 +440,7 @@
 
 static unsigned int r600_texture_is_referenced(struct pipe_context *context,
 						struct pipe_resource *texture,
-						unsigned face, unsigned level)
+						unsigned level, int layer)
 {
 	/* FIXME */
 	return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
@@ -536,7 +532,7 @@
 
 struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx,
 						struct pipe_resource *texture,
-						struct pipe_subresource sr,
+						unsigned level,
 						unsigned usage,
 						const struct pipe_box *box)
 {
@@ -579,7 +575,7 @@
 	if (trans == NULL)
 		return NULL;
 	pipe_resource_reference(&trans->transfer.resource, texture);
-	trans->transfer.sr = sr;
+	trans->transfer.level = level;
 	trans->transfer.usage = usage;
 	trans->transfer.box = *box;
 	if (rtex->depth) {
@@ -600,6 +596,7 @@
 		resource.width0 = box->width;
 		resource.height0 = box->height;
 		resource.depth0 = 1;
+		resource.array_size = 1;
 		resource.last_level = 0;
 		resource.nr_samples = 0;
 		resource.usage = PIPE_USAGE_STAGING;
@@ -633,8 +630,8 @@
 		}
 		return &trans->transfer;
 	}
-	trans->transfer.stride = rtex->pitch_in_bytes[sr.level];
-	trans->offset = r600_texture_get_offset(rtex, sr.level, box->z, sr.face);
+	trans->transfer.stride = rtex->pitch_in_bytes[level];
+	trans->offset = r600_texture_get_offset(rtex, level, box->z);
 	return &trans->transfer;
 }
 
@@ -747,10 +744,10 @@
 	u_default_transfer_inline_write	/* transfer_inline_write */
 };
 
-void r600_init_screen_texture_functions(struct pipe_screen *screen)
+void r600_init_surface_functions(struct r600_pipe_context *r600)
 {
-	screen->get_tex_surface = r600_get_tex_surface;
-	screen->tex_surface_destroy = r600_tex_surface_destroy;
+	r600->context.create_surface = r600_create_surface;
+	r600->context.surface_destroy = r600_surface_destroy;
 }
 
 static unsigned r600_get_swizzle_combined(const unsigned char *swizzle_format,
diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c
index 413da59..94e57e4 100644
--- a/src/gallium/drivers/rbug/rbug_context.c
+++ b/src/gallium/drivers/rbug/rbug_context.c
@@ -707,17 +707,13 @@
 static void
 rbug_resource_copy_region(struct pipe_context *_pipe,
                           struct pipe_resource *_dst,
-                          struct pipe_subresource subdst,
+                          unsigned dst_level,
                           unsigned dstx,
                           unsigned dsty,
                           unsigned dstz,
                           struct pipe_resource *_src,
-                          struct pipe_subresource subsrc,
-                          unsigned srcx,
-                          unsigned srcy,
-                          unsigned srcz,
-                          unsigned width,
-                          unsigned height)
+                          unsigned src_level,
+                          const struct pipe_box *src_box)
 {
    struct rbug_context *rb_pipe = rbug_context(_pipe);
    struct rbug_resource *rb_resource_dst = rbug_resource(_dst);
@@ -728,17 +724,13 @@
 
    pipe->resource_copy_region(pipe,
                               dst,
-                              subdst,
+                              dst_level,
                               dstx,
                               dsty,
                               dstz,
                               src,
-                              subsrc,
-                              srcx,
-                              srcy,
-                              srcz,
-                              width,
-                              height);
+                              src_level,
+                              src_box);
 }
 
 static void
@@ -820,8 +812,8 @@
 static unsigned int
 rbug_is_resource_referenced(struct pipe_context *_pipe,
                             struct pipe_resource *_resource,
-                            unsigned face,
-                            unsigned level)
+                            unsigned level,
+                            int layer)
 {
    struct rbug_context *rb_pipe = rbug_context(_pipe);
    struct rbug_resource *rb_resource = rbug_resource(_resource);
@@ -830,8 +822,8 @@
 
    return pipe->is_resource_referenced(pipe,
                                        resource,
-                                       face,
-                                       level);
+                                       level,
+                                       layer);
 }
 
 static struct pipe_sampler_view *
@@ -862,10 +854,40 @@
                              rbug_sampler_view(_view));
 }
 
+static struct pipe_surface *
+rbug_context_create_surface(struct pipe_context *_pipe,
+                            struct pipe_resource *_resource,
+                            const struct pipe_surface *surf_tmpl)
+{
+   struct rbug_context *rb_pipe = rbug_context(_pipe);
+   struct rbug_resource *rb_resource = rbug_resource(_resource);
+   struct pipe_context *pipe = rb_pipe->pipe;
+   struct pipe_resource *resource = rb_resource->resource;
+   struct pipe_surface *result;
+
+   result = pipe->create_surface(pipe,
+                                 resource,
+                                 surf_tmpl);
+
+   if (result)
+      return rbug_surface_create(rb_pipe, rb_resource, result);
+   return NULL;
+}
+
+static void
+rbug_context_surface_destroy(struct pipe_context *_pipe,
+                             struct pipe_surface *_surface)
+{
+   rbug_surface_destroy(rbug_context(_pipe),
+                        rbug_surface(_surface));
+}
+
+
+
 static struct pipe_transfer *
 rbug_context_get_transfer(struct pipe_context *_context,
                           struct pipe_resource *_resource,
-                          struct pipe_subresource sr,
+                          unsigned level,
                           unsigned usage,
                           const struct pipe_box *box)
 {
@@ -877,7 +899,7 @@
 
    result = context->get_transfer(context,
                                   resource,
-                                  sr,
+                                  level,
                                   usage,
                                   box);
 
@@ -942,12 +964,12 @@
 static void
 rbug_context_transfer_inline_write(struct pipe_context *_context,
                                    struct pipe_resource *_resource,
-                                   struct pipe_subresource sr,
+                                   unsigned level,
                                    unsigned usage,
                                    const struct pipe_box *box,
                                    const void *data,
                                    unsigned stride,
-                                   unsigned slice_stride)
+                                   unsigned layer_stride)
 {
    struct rbug_context *rb_pipe = rbug_context(_context);
    struct rbug_resource *rb_resource = rbug_resource(_resource);
@@ -956,12 +978,12 @@
 
    context->transfer_inline_write(context,
                                   resource,
-                                  sr,
+                                  level,
                                   usage,
                                   box,
                                   data,
                                   stride,
-                                  slice_stride);
+                                  layer_stride);
 }
 
 
@@ -1042,6 +1064,8 @@
    rb_pipe->base.is_resource_referenced = rbug_is_resource_referenced;
    rb_pipe->base.create_sampler_view = rbug_context_create_sampler_view;
    rb_pipe->base.sampler_view_destroy = rbug_context_sampler_view_destroy;
+   rb_pipe->base.create_surface = rbug_context_create_surface;
+   rb_pipe->base.surface_destroy = rbug_context_surface_destroy;
    rb_pipe->base.get_transfer = rbug_context_get_transfer;
    rb_pipe->base.transfer_destroy = rbug_context_transfer_destroy;
    rb_pipe->base.transfer_map = rbug_context_transfer_map;
diff --git a/src/gallium/drivers/rbug/rbug_core.c b/src/gallium/drivers/rbug/rbug_core.c
index 9dc663b..eb772d1 100644
--- a/src/gallium/drivers/rbug/rbug_core.c
+++ b/src/gallium/drivers/rbug/rbug_core.c
@@ -266,9 +266,9 @@
 
    tex = tr_tex->resource;
    t = pipe_get_transfer(context, tex,
-				 gptr->face, gptr->level, gptr->zslice,
-				 PIPE_TRANSFER_READ,
-				 gptr->x, gptr->y, gptr->w, gptr->h);
+                         gptr->level, gptr->face + gptr->zslice,
+                         PIPE_TRANSFER_READ,
+                         gptr->x, gptr->y, gptr->w, gptr->h);
 
    map = context->transfer_map(context, t);
 
@@ -279,7 +279,7 @@
                                 util_format_get_blocksize(t->resource->format),
                                 (uint8_t*)map,
                                 t->stride * util_format_get_nblocksy(t->resource->format,
-								     t->box.height),
+                                                                     t->box.height),
                                 t->stride,
                                 NULL);
 
diff --git a/src/gallium/drivers/rbug/rbug_objects.c b/src/gallium/drivers/rbug/rbug_objects.c
index 0979fcf..7d7cc48 100644
--- a/src/gallium/drivers/rbug/rbug_objects.c
+++ b/src/gallium/drivers/rbug/rbug_objects.c
@@ -79,7 +79,8 @@
 
 
 struct pipe_surface *
-rbug_surface_create(struct rbug_resource *rb_resource,
+rbug_surface_create(struct rbug_context *rb_context,
+                    struct rbug_resource *rb_resource,
                     struct pipe_surface *surface)
 {
    struct rbug_surface *rb_surface;
@@ -108,10 +109,12 @@
 }
 
 void
-rbug_surface_destroy(struct rbug_surface *rb_surface)
+rbug_surface_destroy(struct rbug_context *rb_context,
+                     struct rbug_surface *rb_surface)
 {
    pipe_resource_reference(&rb_surface->base.texture, NULL);
-   pipe_surface_reference(&rb_surface->surface, NULL);
+   rb_context->pipe->surface_destroy(rb_context->pipe,
+                                     rb_surface->surface);
    FREE(rb_surface);
 }
 
diff --git a/src/gallium/drivers/rbug/rbug_objects.h b/src/gallium/drivers/rbug/rbug_objects.h
index 49c128d..3fba333 100644
--- a/src/gallium/drivers/rbug/rbug_objects.h
+++ b/src/gallium/drivers/rbug/rbug_objects.h
@@ -189,11 +189,13 @@
 rbug_resource_destroy(struct rbug_resource *rb_resource);
 
 struct pipe_surface *
-rbug_surface_create(struct rbug_resource *rb_resource,
+rbug_surface_create(struct rbug_context *rb_context,
+                    struct rbug_resource *rb_resource,
                     struct pipe_surface *surface);
 
 void
-rbug_surface_destroy(struct rbug_surface *rb_surface);
+rbug_surface_destroy(struct rbug_context *rb_context,
+                     struct rbug_surface *rb_surface);
 
 struct pipe_sampler_view *
 rbug_sampler_view_create(struct rbug_context *rb_context,
diff --git a/src/gallium/drivers/rbug/rbug_screen.c b/src/gallium/drivers/rbug/rbug_screen.c
index 961df48..d635ce5 100644
--- a/src/gallium/drivers/rbug/rbug_screen.c
+++ b/src/gallium/drivers/rbug/rbug_screen.c
@@ -188,40 +188,6 @@
    rbug_resource_destroy(rbug_resource(_resource));
 }
 
-static struct pipe_surface *
-rbug_screen_get_tex_surface(struct pipe_screen *_screen,
-                            struct pipe_resource *_resource,
-                            unsigned face,
-                            unsigned level,
-                            unsigned zslice,
-                            unsigned usage)
-{
-   struct rbug_screen *rb_screen = rbug_screen(_screen);
-   struct rbug_resource *rb_resource = rbug_resource(_resource);
-   struct pipe_screen *screen = rb_screen->screen;
-   struct pipe_resource *resource = rb_resource->resource;
-   struct pipe_surface *result;
-
-   result = screen->get_tex_surface(screen,
-                                    resource,
-                                    face,
-                                    level,
-                                    zslice,
-                                    usage);
-
-   if (result)
-      return rbug_surface_create(rb_resource, result);
-   return NULL;
-}
-
-static void
-rbug_screen_tex_surface_destroy(struct pipe_surface *_surface)
-{
-   rbug_surface_destroy(rbug_surface(_surface));
-}
-
-
-
 static struct pipe_resource *
 rbug_screen_user_buffer_create(struct pipe_screen *_screen,
                                void *ptr,
@@ -246,16 +212,18 @@
 
 static void
 rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
-                              struct pipe_surface *_surface,
+                              struct pipe_resource *_resource,
+                              unsigned level, unsigned layer,
                               void *context_private)
 {
    struct rbug_screen *rb_screen = rbug_screen(_screen);
-   struct rbug_surface *rb_surface = rbug_surface(_surface);
+   struct rbug_resource *rb_resource = rbug_resource(_resource);
    struct pipe_screen *screen = rb_screen->screen;
-   struct pipe_surface *surface = rb_surface->surface;
+   struct pipe_resource *resource = rb_resource->resource;
 
    screen->flush_frontbuffer(screen,
-                             surface,
+                             resource,
+                             level, layer,
                              context_private);
 }
 
@@ -336,8 +304,6 @@
    rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle;
    rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle;
    rb_screen->base.resource_destroy = rbug_screen_resource_destroy;
-   rb_screen->base.get_tex_surface = rbug_screen_get_tex_surface;
-   rb_screen->base.tex_surface_destroy = rbug_screen_tex_surface_destroy;
    rb_screen->base.user_buffer_create = rbug_screen_user_buffer_create;
    rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer;
    rb_screen->base.fence_reference = rbug_screen_fence_reference;
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index b5d30bc..e935ce6 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -145,15 +145,15 @@
  */
 static unsigned int
 softpipe_is_resource_referenced( struct pipe_context *pipe,
-				struct pipe_resource *texture,
-				unsigned face, unsigned level)
+                                 struct pipe_resource *texture,
+                                 unsigned level, int layer)
 {
    struct softpipe_context *softpipe = softpipe_context( pipe );
    unsigned i;
 
    if (texture->target == PIPE_BUFFER)
       return PIPE_UNREFERENCED;
-   
+
    /* check if any of the bound drawing surfaces are this texture */
    if (softpipe->dirty_render_cache) {
       for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
index 1071011..4258395 100644
--- a/src/gallium/drivers/softpipe/sp_flush.c
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -120,8 +120,8 @@
 boolean
 softpipe_flush_resource(struct pipe_context *pipe,
                         struct pipe_resource *texture,
-                        unsigned face,
                         unsigned level,
+                        int layer,
                         unsigned flush_flags,
                         boolean read_only,
                         boolean cpu_access,
@@ -129,7 +129,7 @@
 {
    unsigned referenced;
 
-   referenced = pipe->is_resource_referenced(pipe, texture, face, level);
+   referenced = pipe->is_resource_referenced(pipe, texture, level, layer);
 
    if ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
        ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) {
diff --git a/src/gallium/drivers/softpipe/sp_flush.h b/src/gallium/drivers/softpipe/sp_flush.h
index cb97482..22a5cee 100644
--- a/src/gallium/drivers/softpipe/sp_flush.h
+++ b/src/gallium/drivers/softpipe/sp_flush.h
@@ -40,8 +40,8 @@
 boolean
 softpipe_flush_resource(struct pipe_context *pipe,
                         struct pipe_resource *texture,
-                        unsigned face,
                         unsigned level,
+                        int layer,
                         unsigned flush_flags,
                         boolean read_only,
                         boolean cpu_access,
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 5f171d3..cbdea19 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -266,12 +266,13 @@
  */
 static void
 softpipe_flush_frontbuffer(struct pipe_screen *_screen,
-                           struct pipe_surface *surface,
+                           struct pipe_resource *resource,
+                           unsigned level, unsigned layer,
                            void *context_private)
 {
    struct softpipe_screen *screen = softpipe_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
-   struct softpipe_resource *texture = softpipe_resource(surface->texture);
+   struct softpipe_resource *texture = softpipe_resource(resource);
 
    assert(texture->dt);
    if (texture->dt)
diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
index e817c0c..7c97539 100644
--- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
@@ -260,15 +260,14 @@
          }
 
          tc->tex_trans = 
-            pipe_get_transfer(tc->pipe, tc->texture, 
-			      addr.bits.face, 
-			      addr.bits.level, 
-			      addr.bits.z, 
-			      PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
-			      0, 0,
-			      u_minify(tc->texture->width0, addr.bits.level),
-			      u_minify(tc->texture->height0, addr.bits.level));
-         
+            pipe_get_transfer(tc->pipe, tc->texture,
+                              addr.bits.level,
+                              addr.bits.face + addr.bits.z,
+                              PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
+                              0, 0,
+                              u_minify(tc->texture->width0, addr.bits.level),
+                              u_minify(tc->texture->height0, addr.bits.level));
+
          tc->tex_trans_map = tc->pipe->transfer_map(tc->pipe, tc->tex_trans);
 
          tc->tex_face = addr.bits.face;
diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
index 05f2513..c2f2a2a 100644
--- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
+++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
@@ -44,6 +44,7 @@
 
 /* If we need to support > 4096, just expand this to be a 64 bit
  * union, or consider tiling in Z as well.
+ * XXX or unify z/face?
  */
 union tex_tile_address {
    struct {
@@ -126,10 +127,10 @@
 
 static INLINE union tex_tile_address
 tex_tile_address( unsigned x,
-		  unsigned y,
-		  unsigned z,
-		  unsigned face,
-		  unsigned level )
+                  unsigned y,
+                  unsigned z,
+                  unsigned face,
+                  unsigned level )
 {
    union tex_tile_address addr;
 
@@ -139,7 +140,7 @@
    addr.bits.z = z;
    addr.bits.face = face;
    addr.bits.level = level;
-      
+
    return addr;
 }
 
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c
index 4e6123f..509d998 100644
--- a/src/gallium/drivers/softpipe/sp_texture.c
+++ b/src/gallium/drivers/softpipe/sp_texture.c
@@ -220,23 +220,18 @@
  */
 static unsigned
 sp_get_tex_image_offset(const struct softpipe_resource *spr,
-                        unsigned level, unsigned face, unsigned zslice)
+                        unsigned level, unsigned layer)
 {
    const unsigned hgt = u_minify(spr->base.height0, level);
    const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt);
    unsigned offset = spr->level_offset[level];
 
-   if (spr->base.target == PIPE_TEXTURE_CUBE) {
-      assert(zslice == 0);
-      offset += face * nblocksy * spr->stride[level];
-   }
-   else if (spr->base.target == PIPE_TEXTURE_3D) {
-      assert(face == 0);
-      offset += zslice * nblocksy * spr->stride[level];
+   if (spr->base.target == PIPE_TEXTURE_CUBE ||
+       spr->base.target == PIPE_TEXTURE_3D) {
+      offset += layer * nblocksy * spr->stride[level];
    }
    else {
-      assert(face == 0);
-      assert(zslice == 0);
+      assert(layer == 0);
    }
 
    return offset;
@@ -247,39 +242,40 @@
  * Get a pipe_surface "view" into a texture resource.
  */
 static struct pipe_surface *
-softpipe_get_tex_surface(struct pipe_screen *screen,
-                         struct pipe_resource *pt,
-                         unsigned face, unsigned level, unsigned zslice,
-                         unsigned usage)
+softpipe_create_surface(struct pipe_context *pipe,
+                        struct pipe_resource *pt,
+                        const struct pipe_surface *surf_tmpl)
 {
-   struct softpipe_resource *spr = softpipe_resource(pt);
    struct pipe_surface *ps;
+   unsigned level = surf_tmpl->u.tex.level;
 
    assert(level <= pt->last_level);
+   assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
 
    ps = CALLOC_STRUCT(pipe_surface);
    if (ps) {
       pipe_reference_init(&ps->reference, 1);
       pipe_resource_reference(&ps->texture, pt);
-      ps->format = pt->format;
+      ps->context = pipe;
+      ps->format = surf_tmpl->format;
       ps->width = u_minify(pt->width0, level);
       ps->height = u_minify(pt->height0, level);
-      ps->offset = sp_get_tex_image_offset(spr, level, face, zslice);
-      ps->usage = usage;
+      ps->usage = surf_tmpl->usage;
 
-      ps->face = face;
-      ps->level = level;
-      ps->zslice = zslice;
+      ps->u.tex.level = level;
+      ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+      ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
    }
    return ps;
 }
 
 
 /**
- * Free a pipe_surface which was created with softpipe_get_tex_surface().
+ * Free a pipe_surface which was created with softpipe_create_surface().
  */
 static void 
-softpipe_tex_surface_destroy(struct pipe_surface *surf)
+softpipe_surface_destroy(struct pipe_context *pipe,
+                         struct pipe_surface *surf)
 {
    /* Effectively do the texture_update work here - if texture images
     * needed post-processing to put them into hardware layout, this is
@@ -302,21 +298,21 @@
  */
 static struct pipe_transfer *
 softpipe_get_transfer(struct pipe_context *pipe,
-		      struct pipe_resource *resource,
-		      struct pipe_subresource sr,
-		      unsigned usage,
-		      const struct pipe_box *box)
+                      struct pipe_resource *resource,
+                      unsigned level,
+                      unsigned usage,
+                      const struct pipe_box *box)
 {
    struct softpipe_resource *spr = softpipe_resource(resource);
    struct softpipe_transfer *spt;
 
    assert(resource);
-   assert(sr.level <= resource->last_level);
+   assert(level <= resource->last_level);
 
    /* make sure the requested region is in the image bounds */
-   assert(box->x + box->width <= u_minify(resource->width0, sr.level));
-   assert(box->y + box->height <= u_minify(resource->height0, sr.level));
-   assert(box->z + box->depth <= u_minify(resource->depth0, sr.level));
+   assert(box->x + box->width <= u_minify(resource->width0, level));
+   assert(box->y + box->height <= u_minify(resource->height0, level));
+   assert(box->z + box->depth <= (u_minify(resource->depth0, level) + resource->array_size - 1));
 
    /*
     * Transfers, like other pipe operations, must happen in order, so flush the
@@ -326,7 +322,7 @@
       boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
       boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
       if (!softpipe_flush_resource(pipe, resource,
-                                   sr.face, sr.level,
+                                   level, box->depth > 1 ? -1 : box->z,
                                    0, /* flush_flags */
                                    read_only,
                                    TRUE, /* cpu_access */
@@ -343,21 +339,21 @@
    if (spt) {
       struct pipe_transfer *pt = &spt->base;
       enum pipe_format format = resource->format;
-      const unsigned hgt = u_minify(spr->base.height0, sr.level);
+      const unsigned hgt = u_minify(spr->base.height0, level);
       const unsigned nblocksy = util_format_get_nblocksy(format, hgt);
 
       pipe_resource_reference(&pt->resource, resource);
-      pt->sr = sr;
+      pt->level = level;
       pt->usage = usage;
       pt->box = *box;
-      pt->stride = spr->stride[sr.level];
-      pt->slice_stride = pt->stride * nblocksy;
+      pt->stride = spr->stride[level];
+      pt->layer_stride = pt->stride * nblocksy;
 
-      spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z);
+      spt->offset = sp_get_tex_image_offset(spr, level, box->z);
  
       spt->offset += 
-	 box->y / util_format_get_blockheight(format) * spt->base.stride +
-	 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
+         box->y / util_format_get_blockheight(format) * spt->base.stride +
+         box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
 
       return pt;
    }
@@ -454,6 +450,7 @@
    spr->base.width0 = bytes;
    spr->base.height0 = 1;
    spr->base.depth0 = 1;
+   spr->base.array_size = 1;
    spr->userBuffer = TRUE;
    spr->data = ptr;
 
@@ -471,6 +468,9 @@
 
    pipe->transfer_flush_region = u_default_transfer_flush_region;
    pipe->transfer_inline_write = u_default_transfer_inline_write;
+
+   pipe->create_surface = softpipe_create_surface;
+   pipe->surface_destroy = softpipe_surface_destroy;
 }
 
 
@@ -483,6 +483,4 @@
    screen->resource_get_handle = softpipe_resource_get_handle;
    screen->user_buffer_create = softpipe_user_buffer_create;
 
-   screen->get_tex_surface = softpipe_get_tex_surface;
-   screen->tex_surface_destroy = softpipe_tex_surface_destroy;
 }
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c
index aa76b8a..4442baf 100644
--- a/src/gallium/drivers/softpipe/sp_tile_cache.c
+++ b/src/gallium/drivers/softpipe/sp_tile_cache.c
@@ -170,11 +170,11 @@
    tc->surface = ps;
 
    if (ps) {
-      tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->face,
-					   ps->level, ps->zslice,
-					   PIPE_TRANSFER_READ_WRITE |
-					   PIPE_TRANSFER_UNSYNCHRONIZED,
-					   0, 0, ps->width, ps->height);
+      tc->transfer = pipe_get_transfer(pipe, ps->texture,
+                                       ps->u.tex.level, ps->u.tex.first_layer,
+                                       PIPE_TRANSFER_READ_WRITE |
+                                       PIPE_TRANSFER_UNSYNCHRONIZED,
+                                       0, 0, ps->width, ps->height);
 
       tc->depth_stencil = (ps->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
                            ps->format == PIPE_FORMAT_Z24X8_UNORM ||
diff --git a/src/gallium/drivers/svga/svga_cmd.c b/src/gallium/drivers/svga/svga_cmd.c
index e975f3b..05eab8a 100644
--- a/src/gallium/drivers/svga/svga_cmd.c
+++ b/src/gallium/drivers/svga/svga_cmd.c
@@ -455,8 +455,8 @@
    cmd->guest.pitch = st->base.stride;
 
    swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags);
-   cmd->host.face = st->base.sr.face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
-   cmd->host.mipmap = st->base.sr.level;
+   cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
+   cmd->host.mipmap = st->base.level;
 
    cmd->transfer = transfer;
 
diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c
index cd3f6b8..1e513f1 100644
--- a/src/gallium/drivers/svga/svga_context.c
+++ b/src/gallium/drivers/svga/svga_context.c
@@ -109,6 +109,7 @@
    svga_init_vertex_functions(svga);
    svga_init_constbuffer_functions(svga);
    svga_init_query_functions(svga);
+   svga_init_surface_functions(svga);
 
 
    /* debug */
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index 1fb5a04..04e281a 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -422,6 +422,7 @@
 void svga_init_constbuffer_functions( struct svga_context *svga );
 void svga_init_draw_functions( struct svga_context *svga );
 void svga_init_query_functions( struct svga_context *svga );
+void svga_init_surface_functions(struct svga_context *svga);
 
 void svga_cleanup_vertex_state( struct svga_context *svga );
 void svga_cleanup_tss_binding( struct svga_context *svga );
diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c
index ca036a6..4266988 100644
--- a/src/gallium/drivers/svga/svga_pipe_blit.c
+++ b/src/gallium/drivers/svga/svga_pipe_blit.c
@@ -32,37 +32,40 @@
 #define FILE_DEBUG_FLAG DEBUG_BLIT
 
 
-/* XXX I got my doubts about this, should maybe use svga_texture_copy_handle directly? */
+/* XXX still have doubts about this... */
 static void svga_surface_copy(struct pipe_context *pipe,
                               struct pipe_resource* dst_tex,
-                              struct pipe_subresource subdst,
+                              unsigned dst_level,
                               unsigned dstx, unsigned dsty, unsigned dstz,
                               struct pipe_resource* src_tex,
-                              struct pipe_subresource subsrc,
-                              unsigned srcx, unsigned srcy, unsigned srcz,
-                              unsigned width, unsigned height)
-{
+                              unsigned src_level,
+                              const struct pipe_box *src_box)
+ {
    struct svga_context *svga = svga_context(pipe);
-   struct pipe_screen *screen = pipe->screen;
+   struct svga_texture *stex = svga_texture(src_tex);
+   struct svga_texture *dtex = svga_texture(dst_tex);
+/*   struct pipe_screen *screen = pipe->screen;
    SVGA3dCopyBox *box;
    enum pipe_error ret;
-   struct pipe_surface *srcsurf, *dstsurf;
+   struct pipe_surface *srcsurf, *dstsurf;*/
+   unsigned dst_face, dst_z, src_face, src_z;
 
    svga_hwtnl_flush_retry( svga );
 
+#if 0
    srcsurf = screen->get_tex_surface(screen, src_tex,
-                                     subsrc.face, subsrc.level, srcz,
+                                     src_level, src_box->z, src_box->z,
                                      PIPE_BIND_SAMPLER_VIEW);
 
    dstsurf = screen->get_tex_surface(screen, dst_tex,
-                                     subdst.face, subdst.level, dstz,
+                                     dst_level, dst_box->z, dst_box->z,
                                      PIPE_BIND_RENDER_TARGET);
 
    SVGA_DBG(DEBUG_DMA, "blit to sid %p (%d,%d), from sid %p (%d,%d) sz %dx%d\n",
             svga_surface(dstsurf)->handle,
             dstx, dsty,
             svga_surface(srcsurf)->handle,
-            srcx, srcy,
+            src_box->x, src_box->y,
             width, height);
 
    ret = SVGA3D_BeginSurfaceCopy(svga->swc,
@@ -88,8 +91,8 @@
    box->w = width;
    box->h = height;
    box->d = 1;
-   box->srcx = srcx;
-   box->srcy = srcy;
+   box->srcx = src_box->x;
+   box->srcy = src_box->y;
    box->srcz = 0;
 
    SVGA_FIFOCommitAll(svga->swc);
@@ -100,6 +103,37 @@
    pipe_surface_reference(&srcsurf, NULL);
    pipe_surface_reference(&dstsurf, NULL);
 
+#else
+   if (src_tex->target == PIPE_TEXTURE_CUBE) {
+      src_face = src_box->z;
+      src_z = 0;
+      assert(src_box->depth == 1);
+   }
+   else {
+      src_face = 0;
+      src_z = src_box->z;
+   }
+   /* different src/dst type???*/
+   if (dst_tex->target == PIPE_TEXTURE_CUBE) {
+      dst_face = dstz;
+      dst_z = 0;
+      assert(src_box->depth == 1);
+   }
+   else {
+      dst_face = 0;
+      dst_z = dstz;
+   }
+   svga_texture_copy_handle(svga,
+                            stex->handle,
+                            src_box->x, src_box->y, src_z,
+                            src_level, src_face,
+                            dtex->handle,
+                            dstx, dsty, dst_z,
+                            dst_level, dst_face,
+                            src_box->width, src_box->height, src_box->depth);
+
+#endif
+
 }
 
 
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c
index 198d401..f12e2b6 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer.c
@@ -53,8 +53,8 @@
 
 static unsigned int
 svga_buffer_is_referenced( struct pipe_context *pipe,
-			     struct pipe_resource *buf,
-			     unsigned face, unsigned level)
+                           struct pipe_resource *buf,
+                           unsigned level, int layer)
 {
    struct svga_screen *ss = svga_screen(pipe->screen);
    struct svga_buffer *sbuf = svga_buffer(buf);
@@ -337,6 +337,7 @@
    sbuf->b.b.width0 = bytes;
    sbuf->b.b.height0 = 1;
    sbuf->b.b.depth0 = 1;
+   sbuf->b.b.array_size = 1;
 
    sbuf->swbuf = ptr;
    sbuf->user = TRUE;
diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c
index 26eb03a..7c9e600 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.c
+++ b/src/gallium/drivers/svga/svga_resource_texture.c
@@ -50,8 +50,8 @@
 
 static unsigned int
 svga_texture_is_referenced( struct pipe_context *pipe,
-			    struct pipe_resource *texture,
-			    unsigned face, unsigned level)
+                            struct pipe_resource *texture,
+                            unsigned level, int layer)
 {
    struct svga_texture *tex = svga_texture(texture);
    struct svga_screen *ss = svga_screen(pipe->screen);
@@ -171,20 +171,7 @@
    struct svga_texture *texture = svga_texture(st->base.resource); 
    SVGA3dCopyBox box;
    enum pipe_error ret;
-   
-   SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - (%u, %u, %u), %ubpp\n",
-                transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from", 
-                texture->handle,
-                st->base.sr.face,
-                st->base.box.x,
-                y,
-                st->base.box.z,
-                st->base.box.x + st->base.box.width,
-                y + h,
-                st->base.box.z + 1,
-                util_format_get_blocksize(texture->b.b.format) * 8 /
-                (util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format)));
-   
+ 
    box.x = st->base.box.x;
    box.y = y;
    box.z = st->base.box.z;
@@ -195,6 +182,26 @@
    box.srcy = srcy;
    box.srcz = 0;
 
+   if (st->base.resource->target == PIPE_TEXTURE_CUBE) {
+      st->face = st->base.box.z;
+      box.z = 0;
+   }
+   else
+      st->face = 0;
+
+   SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - (%u, %u, %u), %ubpp\n",
+                transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from", 
+                texture->handle,
+                st->face,
+                st->base.box.x,
+                y,
+                box.z,
+                st->base.box.x + st->base.box.width,
+                y + h,
+                box.z + 1,
+                util_format_get_blocksize(texture->b.b.format) * 8 /
+                (util_format_get_blockwidth(texture->b.b.format)*util_format_get_blockheight(texture->b.b.format)));
+
    ret = SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1);
    if(ret != PIPE_OK) {
       svga->swc->flush(svga->swc, NULL);
@@ -213,7 +220,7 @@
    struct svga_screen *screen = svga_screen(texture->b.b.screen);
    struct svga_winsys_screen *sws = screen->sws;
    struct pipe_fence_handle *fence = NULL;
-   
+
    if (transfer == SVGA3D_READ_HOST_VRAM) {
       SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __FUNCTION__);
    }
@@ -221,7 +228,7 @@
 
    if(!st->swbuf) {
       /* Do the DMA transfer in a single go */
-      
+
       svga_transfer_dma_band(svga, st, transfer, st->base.box.y, st->base.box.height, 0);
 
       if(transfer == SVGA3D_READ_HOST_VRAM) {
@@ -245,12 +252,12 @@
          /* Transfer band must be aligned to pixel block boundaries */
          assert(y % blockheight == 0);
          assert(h % blockheight == 0);
-         
+
          offset = y * st->base.stride / blockheight;
          length = h * st->base.stride / blockheight;
 
          sw = (uint8_t *)st->swbuf + offset;
-         
+
          if(transfer == SVGA3D_WRITE_HOST_VRAM) {
             /* Wait for the previous DMAs to complete */
             /* TODO: keep one DMA (at half the size) in the background */
@@ -267,9 +274,9 @@
                sws->buffer_unmap(sws, st->hwbuf);
             }
          }
-         
+
          svga_transfer_dma_band(svga, st, transfer, y, h, srcy);
-         
+
          if(transfer == SVGA3D_READ_HOST_VRAM) {
             svga_context_flush(svga, &fence);
             sws->fence_finish(sws, fence, 0);
@@ -336,10 +343,10 @@
  */
 static struct pipe_transfer *
 svga_texture_get_transfer(struct pipe_context *pipe,
-			  struct pipe_resource *texture,
-			  struct pipe_subresource sr,
-			  unsigned usage,
-			  const struct pipe_box *box)
+                          struct pipe_resource *texture,
+                          unsigned level,
+                          unsigned usage,
+                          const struct pipe_box *box)
 {
    struct svga_context *svga = svga_context(pipe);
    struct svga_screen *ss = svga_screen(pipe->screen);
@@ -352,19 +359,20 @@
    if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
       return NULL;
 
+   assert(box->depth == 1);
    st = CALLOC_STRUCT(svga_transfer);
    if (!st)
       return NULL;
-   
+
    pipe_resource_reference(&st->base.resource, texture);
-   st->base.sr = sr;
+   st->base.level = level;
    st->base.usage = usage;
    st->base.box = *box;
    st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
-   st->base.slice_stride = 0;
+   st->base.layer_stride = 0;
 
    st->hw_nblocksy = nblocksy;
-   
+
    st->hwbuf = svga_winsys_buffer_create(svga,
                                          1, 
                                          0,
@@ -391,7 +399,7 @@
       if(!st->swbuf)
          goto no_swbuf;
    }
-   
+
    if (usage & PIPE_TRANSFER_READ)
       svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM);
 
@@ -454,8 +462,11 @@
    if (st->base.usage & PIPE_TRANSFER_WRITE) {
       svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM);
       ss->texture_timestamp++;
-      tex->view_age[transfer->sr.level] = ++(tex->age);
-      tex->defined[transfer->sr.face][transfer->sr.level] = TRUE;
+      tex->view_age[transfer->level] = ++(tex->age);
+      if (transfer->resource->target == PIPE_TEXTURE_CUBE)
+         tex->defined[transfer->box.z][transfer->level] = TRUE;
+      else
+         tex->defined[0][transfer->level] = TRUE;
    }
 
    pipe_resource_reference(&st->base.resource, NULL);
@@ -490,7 +501,7 @@
 {
    struct svga_screen *svgascreen = svga_screen(screen);
    struct svga_texture *tex = CALLOC_STRUCT(svga_texture);
-   
+
    if (!tex)
       goto error1;
 
@@ -507,7 +518,7 @@
    tex->key.size.width = template->width0;
    tex->key.size.height = template->height0;
    tex->key.size.depth = template->depth0;
-   
+
    if(template->target == PIPE_TEXTURE_CUBE) {
       tex->key.flags |= SVGA3D_SURFACE_CUBEMAP;
       tex->key.numFaces = 6;
diff --git a/src/gallium/drivers/svga/svga_resource_texture.h b/src/gallium/drivers/svga/svga_resource_texture.h
index 631937f..9a2911c 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.h
+++ b/src/gallium/drivers/svga/svga_resource_texture.h
@@ -85,6 +85,8 @@
 {
    struct pipe_transfer base;
 
+   unsigned face;
+
    struct svga_winsys_buffer *hwbuf;
 
    /* Height of the hardware buffer in pixel blocks */
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index 666b498..0781903 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -499,7 +499,6 @@
    screen->fence_finish = svga_fence_finish;
    svgascreen->sws = sws;
 
-   svga_screen_init_surface_functions(screen);
    svga_init_screen_resource_functions(svgascreen);
 
    svgascreen->use_ps30 =
diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c
index b21dc5f..3e4bed7 100644
--- a/src/gallium/drivers/svga/svga_surface.c
+++ b/src/gallium/drivers/svga/svga_surface.c
@@ -179,36 +179,50 @@
 
 
 static struct pipe_surface *
-svga_get_tex_surface(struct pipe_screen *screen,
-                     struct pipe_resource *pt,
-                     unsigned face, unsigned level, unsigned zslice,
-                     unsigned flags)
+svga_create_surface(struct pipe_context *pipe,
+                    struct pipe_resource *pt,
+                    const struct pipe_surface *surf_tmpl)
 {
    struct svga_texture *tex = svga_texture(pt);
+   struct pipe_screen *screen = pipe->screen;
    struct svga_surface *s;
-   boolean render = (flags & (PIPE_BIND_RENDER_TARGET |
-			      PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE;
+   unsigned face, zslice;
+   /* XXX surfaces should only be used for rendering purposes nowadays */
+   boolean render = (surf_tmpl->usage & (PIPE_BIND_RENDER_TARGET |
+                                         PIPE_BIND_DEPTH_STENCIL)) ? TRUE : FALSE;
    boolean view = FALSE;
    SVGA3dSurfaceFormat format;
 
+   assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
+
    s = CALLOC_STRUCT(svga_surface);
    if (!s)
       return NULL;
 
+   if (pt->target == PIPE_TEXTURE_CUBE) {
+         face = surf_tmpl->u.tex.first_layer;
+         zslice = 0;
+   }
+   else {
+      face = 0;
+      zslice = surf_tmpl->u.tex.first_layer;
+   }
+
    pipe_reference_init(&s->base.reference, 1);
    pipe_resource_reference(&s->base.texture, pt);
-   s->base.format = pt->format;
-   s->base.width = u_minify(pt->width0, level);
-   s->base.height = u_minify(pt->height0, level);
-   s->base.usage = flags;
-   s->base.level = level;
-   s->base.face = face;
-   s->base.zslice = zslice;
+   s->base.context = pipe;
+   s->base.format = surf_tmpl->format;
+   s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
+   s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
+   s->base.usage = surf_tmpl->usage;
+   s->base.u.tex.level = surf_tmpl->u.tex.level;
+   s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
+   s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
 
    if (!render)
-      format = svga_translate_format(pt->format);
+      format = svga_translate_format(surf_tmpl->format);
    else
-      format = svga_translate_format_render(pt->format);
+      format = svga_translate_format_render(surf_tmpl->format);
 
    assert(format != SVGA3D_FORMAT_INVALID);
 
@@ -217,11 +231,11 @@
 
    /* Currently only used for compressed textures */
    if (render && 
-       format != svga_translate_format(pt->format)) {
+       format != svga_translate_format(surf_tmpl->format)) {
       view = TRUE;
    }
 
-   if (level != 0 && 
+   if (surf_tmpl->u.tex.level != 0 &&
        svga_screen(screen)->debug.force_level_surface_view)
       view = TRUE;
 
@@ -233,22 +247,22 @@
 
    if (view) {
       SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n",
-               pt, level, face, zslice, s);
+               pt, surf_tmpl->u.tex.level, face, zslice, s);
 
-      s->handle = svga_texture_view_surface(NULL, tex, format, level, 1, face, zslice,
-                                            &s->key);
+      s->handle = svga_texture_view_surface(NULL, tex, format, surf_tmpl->u.tex.level,
+	                                    1, face, zslice, &s->key);
       s->real_face = 0;
       s->real_level = 0;
       s->real_zslice = 0;
    } else {
       SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, face %u, z %u, %p\n",
-               pt, level, face, zslice, s);
+               pt, surf_tmpl->u.tex.level, face, zslice, s);
 
       memset(&s->key, 0, sizeof s->key);
       s->handle = tex->handle;
       s->real_face = face;
-      s->real_level = level;
       s->real_zslice = zslice;
+      s->real_level = surf_tmpl->u.tex.level;
    }
 
    return &s->base;
@@ -256,7 +270,8 @@
 
 
 static void
-svga_tex_surface_destroy(struct pipe_surface *surf)
+svga_surface_destroy(struct pipe_context *pipe,
+                     struct pipe_surface *surf)
 {
    struct svga_surface *s = svga_surface(surf);
    struct svga_texture *t = svga_texture(surf->texture);
@@ -282,8 +297,13 @@
 
       s->dirty = TRUE;
 
-      if (s->handle == tex->handle)
-         tex->defined[surf->face][surf->level] = TRUE;
+      if (s->handle == tex->handle) {
+         /* hmm so 3d textures always have all their slices marked ? */
+         if (surf->texture->target == PIPE_TEXTURE_CUBE)
+            tex->defined[surf->u.tex.first_layer][surf->u.tex.level] = TRUE;
+         else
+            tex->defined[0][surf->u.tex.level] = TRUE;
+      }
       else {
          /* this will happen later in svga_propagate_surface */
       }
@@ -314,22 +334,32 @@
    struct svga_surface *s = svga_surface(surf);
    struct svga_texture *tex = svga_texture(surf->texture);
    struct svga_screen *ss = svga_screen(surf->texture->screen);
+   unsigned zslice, face;
 
    if (!s->dirty)
       return;
 
+   if (surf->texture->target == PIPE_TEXTURE_CUBE) {
+      zslice = 0;
+      face = surf->u.tex.first_layer;
+   }
+   else {
+      zslice = surf->u.tex.first_layer;
+      face = 0;
+   }
+
    s->dirty = FALSE;
    ss->texture_timestamp++;
-   tex->view_age[surf->level] = ++(tex->age);
+   tex->view_age[surf->u.tex.level] = ++(tex->age);
 
    if (s->handle != tex->handle) {
-      SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->level, surf);
+      SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf);
       svga_texture_copy_handle(svga_context(pipe),
                                s->handle, 0, 0, 0, s->real_level, s->real_face,
-                               tex->handle, 0, 0, surf->zslice, surf->level, surf->face,
-                               u_minify(tex->b.b.width0, surf->level),
-                               u_minify(tex->b.b.height0, surf->level), 1);
-      tex->defined[surf->face][surf->level] = TRUE;
+                               tex->handle, 0, 0, zslice, surf->u.tex.level, face,
+                               u_minify(tex->b.b.width0, surf->u.tex.level),
+                               u_minify(tex->b.b.height0, surf->u.tex.level), 1);
+      tex->defined[face][surf->u.tex.level] = TRUE;
    }
 }
 
@@ -351,9 +381,9 @@
 
 
 void
-svga_screen_init_surface_functions(struct pipe_screen *screen)
+svga_init_surface_functions(struct svga_context *svga)
 {
-   screen->get_tex_surface = svga_get_tex_surface;
-   screen->tex_surface_destroy = svga_tex_surface_destroy;
+   svga->pipe.create_surface = svga_create_surface;
+   svga->pipe.surface_destroy = svga_surface_destroy;
 }
 
diff --git a/src/gallium/drivers/svga/svga_surface.h b/src/gallium/drivers/svga/svga_surface.h
index 13bd5b1..afb8326 100644
--- a/src/gallium/drivers/svga/svga_surface.h
+++ b/src/gallium/drivers/svga/svga_surface.h
@@ -90,7 +90,4 @@
    return (struct svga_surface *)surface;
 }
 
-void
-svga_screen_init_surface_functions(struct pipe_screen *screen);
-
 #endif
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 04f30f8..2fdb6c9 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -885,6 +885,60 @@
    FREE(_view);
 }
 
+/********************************************************************
+ * surface
+ */
+
+
+static struct pipe_surface *
+trace_create_surface(struct pipe_context *_pipe,
+                     struct pipe_resource *_texture,
+                     const struct pipe_surface *surf_tmpl)
+{
+   struct trace_context *tr_ctx = trace_context(_pipe);
+   struct trace_resource *tr_tex = trace_resource(_texture);
+   struct pipe_context *pipe = tr_ctx->pipe;
+   struct pipe_resource *texture = tr_tex->resource;
+   struct pipe_surface *result = NULL;
+
+   trace_dump_call_begin("pipe_context", "create_surface");
+
+   trace_dump_arg(ptr, pipe);
+   trace_dump_arg(ptr, texture);
+   /* hmm some values unitialized there */
+   trace_dump_arg(surface, surf_tmpl);
+
+   result = pipe->create_surface(pipe, texture, surf_tmpl);
+
+   trace_dump_ret(ptr, result);
+
+   trace_dump_call_end();
+
+   result = trace_surf_create(tr_tex, result);
+
+   return result;
+}
+
+
+static void
+trace_surface_destroy(struct pipe_context *_pipe,
+                      struct pipe_surface *_surface)
+{
+   struct trace_context *tr_ctx = trace_context(_pipe);
+   struct pipe_context *pipe = tr_ctx->pipe;
+   struct trace_surface *tr_surf = trace_surface(_surface);
+   struct pipe_surface *surface = tr_surf->surface;
+
+   trace_dump_call_begin("pipe_context", "surface_destroy");
+
+   trace_dump_arg(ptr, pipe);
+   trace_dump_arg(ptr, surface);
+
+   trace_dump_call_end();
+
+   trace_surf_destroy(tr_surf);
+}
+
 
 static INLINE void
 trace_context_set_fragment_sampler_views(struct pipe_context *_pipe,
@@ -1004,12 +1058,11 @@
 static INLINE void
 trace_context_resource_copy_region(struct pipe_context *_pipe,
                                    struct pipe_resource *dst,
-                                   struct pipe_subresource subdst,
+                                   unsigned dst_level,
                                    unsigned dstx, unsigned dsty, unsigned dstz,
                                    struct pipe_resource *src,
-                                   struct pipe_subresource subsrc,
-                                   unsigned srcx, unsigned srcy, unsigned srcz,
-                                   unsigned width, unsigned height)
+                                   unsigned src_level,
+                                   const struct pipe_box *src_box)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
    struct pipe_context *pipe = tr_ctx->pipe;
@@ -1021,21 +1074,17 @@
 
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(ptr, dst);
-   trace_dump_arg_struct(subresource, subdst);
+   trace_dump_arg(uint, dst_level);
    trace_dump_arg(uint, dstx);
    trace_dump_arg(uint, dsty);
    trace_dump_arg(uint, dstz);
    trace_dump_arg(ptr, src);
-   trace_dump_arg_struct(subresource, subsrc);
-   trace_dump_arg(uint, srcx);
-   trace_dump_arg(uint, srcy);
-   trace_dump_arg(uint, srcz);
-   trace_dump_arg(uint, width);
-   trace_dump_arg(uint, height);
+   trace_dump_arg(uint, src_level);
+   trace_dump_arg(box, src_box);
 
    pipe->resource_copy_region(pipe,
-                              dst, subdst, dstx, dsty, dstz,
-                              src, subsrc, srcx, srcy, srcz, width, height);
+                              dst, dst_level, dstx, dsty, dstz,
+                              src, src_level, src_box);
 
    trace_dump_call_end();
 }
@@ -1166,8 +1215,8 @@
 
 static unsigned int
 trace_is_resource_referenced( struct pipe_context *_pipe,
-			      struct pipe_resource *_resource,
-			      unsigned face, unsigned level)
+                              struct pipe_resource *_resource,
+                              unsigned level, int layer)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
    struct trace_resource *tr_tex = trace_resource(_resource);
@@ -1178,10 +1227,10 @@
    trace_dump_call_begin("pipe_context", "is_resource_referenced");
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(ptr, texture);
-   trace_dump_arg(uint, face);
    trace_dump_arg(uint, level);
+   trace_dump_arg(int, layer);
 
-   referenced = pipe->is_resource_referenced(pipe, texture, face, level);
+   referenced = pipe->is_resource_referenced(pipe, texture, level, layer);
 
    trace_dump_ret(uint, referenced);
    trace_dump_call_end();
@@ -1197,10 +1246,10 @@
 
 static struct pipe_transfer *
 trace_context_get_transfer(struct pipe_context *_context,
-			   struct pipe_resource *_resource,
-			   struct pipe_subresource sr,
-			   unsigned usage,
-			   const struct pipe_box *box)
+                           struct pipe_resource *_resource,
+                           unsigned level,
+                           unsigned usage,
+                           const struct pipe_box *box)
 {
    struct trace_context *tr_context = trace_context(_context);
    struct trace_resource *tr_tex = trace_resource(_resource);
@@ -1215,7 +1264,7 @@
     * to transfer_inline_write and ignore read transfers.
     */
 
-   result = context->get_transfer(context, texture, sr, usage, box);
+   result = context->get_transfer(context, texture, level, usage, box);
 
    if (result)
       result = trace_transfer_create(tr_context, tr_tex, result);
@@ -1226,7 +1275,7 @@
 
 static void
 trace_context_transfer_destroy(struct pipe_context *_context,
-                                   struct pipe_transfer *_transfer)
+                               struct pipe_transfer *_transfer)
 {
    struct trace_context *tr_context = trace_context(_context);
    struct trace_transfer *tr_trans = trace_transfer(_transfer);
@@ -1274,7 +1323,7 @@
 
 static void
 trace_context_transfer_unmap(struct pipe_context *_context,
-			     struct pipe_transfer *_transfer)
+                             struct pipe_transfer *_transfer)
 {
    struct trace_context *tr_ctx = trace_context(_context);
    struct trace_transfer *tr_trans = trace_transfer(_transfer);
@@ -1287,17 +1336,17 @@
        */
 
       struct pipe_resource *resource = transfer->resource;
-      struct pipe_subresource sr = transfer->sr;
+      unsigned level = transfer->level;
       unsigned usage = transfer->usage;
       const struct pipe_box *box = &transfer->box;
       unsigned stride = transfer->stride;
-      unsigned slice_stride = transfer->slice_stride;
+      unsigned layer_stride = transfer->layer_stride;
 
       trace_dump_call_begin("pipe_context", "transfer_inline_write");
 
       trace_dump_arg(ptr, context);
       trace_dump_arg(ptr, resource);
-      trace_dump_arg_struct(subresource, sr);
+      trace_dump_arg(uint, level);
       trace_dump_arg(uint, usage);
       trace_dump_arg(box, box);
 
@@ -1306,11 +1355,11 @@
                            resource->format,
                            box,
                            stride,
-                           slice_stride);
+                           layer_stride);
       trace_dump_arg_end();
 
       trace_dump_arg(uint, stride);
-      trace_dump_arg(uint, slice_stride);
+      trace_dump_arg(uint, layer_stride);
 
       trace_dump_call_end();
 
@@ -1323,13 +1372,13 @@
 
 static void
 trace_context_transfer_inline_write(struct pipe_context *_context,
-				    struct pipe_resource *_resource,
-				    struct pipe_subresource sr,
-				    unsigned usage,
-				    const struct pipe_box *box,
-				    const void *data,
-				    unsigned stride,
-				    unsigned slice_stride)
+                                    struct pipe_resource *_resource,
+                                    unsigned level,
+                                    unsigned usage,
+                                    const struct pipe_box *box,
+                                    const void *data,
+                                    unsigned stride,
+                                    unsigned layer_stride)
 {
    struct trace_context *tr_context = trace_context(_context);
    struct trace_resource *tr_tex = trace_resource(_resource);
@@ -1342,7 +1391,7 @@
 
    trace_dump_arg(ptr, context);
    trace_dump_arg(ptr, resource);
-   trace_dump_arg_struct(subresource, sr);
+   trace_dump_arg(uint, level);
    trace_dump_arg(uint, usage);
    trace_dump_arg(box, box);
 
@@ -1351,16 +1400,16 @@
                         resource->format,
                         box,
                         stride,
-                        slice_stride);
+                        layer_stride);
    trace_dump_arg_end();
 
    trace_dump_arg(uint, stride);
-   trace_dump_arg(uint, slice_stride);
+   trace_dump_arg(uint, layer_stride);
 
    trace_dump_call_end();
 
    context->transfer_inline_write(context, resource,
-				  sr, usage, box, data, stride, slice_stride);
+                                  level, usage, box, data, stride, layer_stride);
 }
 
 
@@ -1434,6 +1483,8 @@
    tr_ctx->base.set_vertex_sampler_views = trace_context_set_vertex_sampler_views;
    tr_ctx->base.create_sampler_view = trace_create_sampler_view;
    tr_ctx->base.sampler_view_destroy = trace_sampler_view_destroy;
+   tr_ctx->base.create_surface = trace_create_surface;
+   tr_ctx->base.surface_destroy = trace_surface_destroy;
    tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers;
    tr_ctx->base.set_index_buffer = trace_context_set_index_buffer;
    tr_ctx->base.resource_copy_region = trace_context_resource_copy_region;
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index 8f81606..155c869 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -71,6 +71,10 @@
    trace_dump_uint(templat->depth0);
    trace_dump_member_end();
 
+   trace_dump_member_begin("array_size");
+   trace_dump_uint(templat->array_size);
+   trace_dump_member_end();
+
    trace_dump_member(uint, templat, last_level);
    trace_dump_member(uint, templat, usage);
    trace_dump_member(uint, templat, bind);
@@ -80,25 +84,6 @@
 }
 
 
-void trace_dump_subresource(const struct pipe_subresource *subresource)
-{
-   if (!trace_dumping_enabled_locked())
-      return;
-
-   if(!subresource) {
-      trace_dump_null();
-      return;
-   }
-
-   trace_dump_struct_begin("pipe_subresource");
-
-   trace_dump_member(uint, subresource, face);
-   trace_dump_member(uint, subresource, level);
-
-   trace_dump_struct_end();
-}
-
-
 void trace_dump_box(const struct pipe_box *box)
 {
    if (!trace_dumping_enabled_locked())
@@ -445,8 +430,13 @@
    trace_dump_struct_begin("pipe_sampler_view");
 
    trace_dump_member(format, state, format);
-   trace_dump_member(uint, state, first_level);
-   trace_dump_member(uint, state, last_level);
+   /* XXX */
+   trace_dump_member(uint, state, u.tex.first_level);
+   trace_dump_member(uint, state, u.tex.last_level);
+   trace_dump_member(uint, state, u.tex.first_layer);
+   trace_dump_member(uint, state, u.tex.last_layer);
+   trace_dump_member(uint, state, u.buf.first_element);
+   trace_dump_member(uint, state, u.buf.last_element);
    trace_dump_member(uint, state, swizzle_r);
    trace_dump_member(uint, state, swizzle_g);
    trace_dump_member(uint, state, swizzle_b);
@@ -472,14 +462,14 @@
    trace_dump_member(uint, state, width);
    trace_dump_member(uint, state, height);
 
-   trace_dump_member(uint, state, layout);
-   trace_dump_member(uint, state, offset);
    trace_dump_member(uint, state, usage);
 
    trace_dump_member(ptr, state, texture);
-   trace_dump_member(uint, state, face);
-   trace_dump_member(uint, state, level);
-   trace_dump_member(uint, state, zslice);
+   trace_dump_member(uint, state, u.tex.level);
+   trace_dump_member(uint, state, u.tex.first_layer);
+   trace_dump_member(uint, state, u.tex.last_layer);
+   trace_dump_member(uint, state, u.buf.first_element);
+   trace_dump_member(uint, state, u.buf.last_element);
 
    trace_dump_struct_end();
 }
@@ -497,16 +487,18 @@
 
    trace_dump_struct_begin("pipe_transfer");
 
+   trace_dump_member(uint, state, box.x);
+   trace_dump_member(uint, state, box.y);
+   trace_dump_member(uint, state, box.z);
    trace_dump_member(uint, state, box.width);
    trace_dump_member(uint, state, box.height);
+   trace_dump_member(uint, state, box.depth);
 
    trace_dump_member(uint, state, stride);
+   trace_dump_member(uint, state, layer_stride);
    trace_dump_member(uint, state, usage);
 
    trace_dump_member(ptr, state, resource);
-   trace_dump_member(uint, state, sr.face);
-   trace_dump_member(uint, state, sr.level);
-   trace_dump_member(uint, state, box.z);
 
    trace_dump_struct_end();
 }
diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h
index 078d208..fe8ece78d 100644
--- a/src/gallium/drivers/trace/tr_dump_state.h
+++ b/src/gallium/drivers/trace/tr_dump_state.h
@@ -37,8 +37,6 @@
 
 void trace_dump_resource_template(const struct pipe_resource *templat);
 
-void trace_dump_subresource(const struct pipe_subresource *subresource);
-
 void trace_dump_box(const struct pipe_box *box);
 
 void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state);
diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
index 9358310..c2de2da 100644
--- a/src/gallium/drivers/trace/tr_screen.c
+++ b/src/gallium/drivers/trace/tr_screen.c
@@ -210,23 +210,26 @@
 
 static void
 trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
-                               struct pipe_surface *_surface,
+                               struct pipe_resource *_resource,
+                               unsigned level, unsigned layer,
                                void *context_private)
 {
    struct trace_screen *tr_scr = trace_screen(_screen);
-   struct trace_surface *tr_surf = trace_surface(_surface);
+   struct trace_resource *tr_res = trace_resource(_resource);
    struct pipe_screen *screen = tr_scr->screen;
-   struct pipe_surface *surface = tr_surf->surface;
+   struct pipe_resource *resource = tr_res->resource;
 
    trace_dump_call_begin("pipe_screen", "flush_frontbuffer");
 
    trace_dump_arg(ptr, screen);
-   trace_dump_arg(ptr, surface);
+   trace_dump_arg(ptr, resource);
+   trace_dump_arg(uint, level);
+   trace_dump_arg(uint, layer);
    /* XXX: hide, as there is nothing we can do with this
    trace_dump_arg(ptr, context_private);
    */
 
-   screen->flush_frontbuffer(screen, surface, context_private);
+   screen->flush_frontbuffer(screen, resource, level, layer, context_private);
 
    trace_dump_call_end();
 }
@@ -318,68 +321,6 @@
 }
 
 
-/********************************************************************
- * surface
- */
-
-
-static struct pipe_surface *
-trace_screen_get_tex_surface(struct pipe_screen *_screen,
-                             struct pipe_resource *_texture,
-                             unsigned face, unsigned level,
-                             unsigned zslice,
-                             unsigned usage)
-{
-   struct trace_screen *tr_scr = trace_screen(_screen);
-   struct trace_resource *tr_tex = trace_resource(_texture);
-   struct pipe_screen *screen = tr_scr->screen;
-   struct pipe_resource *texture = tr_tex->resource;
-   struct pipe_surface *result = NULL;
-
-   assert(texture->screen == screen);
-
-   trace_dump_call_begin("pipe_screen", "get_tex_surface");
-
-   trace_dump_arg(ptr, screen);
-   trace_dump_arg(ptr, texture);
-   trace_dump_arg(uint, face);
-   trace_dump_arg(uint, level);
-   trace_dump_arg(uint, zslice);
-   trace_dump_arg(uint, usage);
-
-   result = screen->get_tex_surface(screen, texture, face, level, zslice, usage);
-
-   trace_dump_ret(ptr, result);
-
-   trace_dump_call_end();
-
-   result = trace_surface_create(tr_tex, result);
-
-   return result;
-}
-
-
-static void
-trace_screen_tex_surface_destroy(struct pipe_surface *_surface)
-{
-   struct trace_screen *tr_scr = trace_screen(_surface->texture->screen);
-   struct trace_surface *tr_surf = trace_surface(_surface);
-   struct pipe_screen *screen = tr_scr->screen;
-   struct pipe_surface *surface = tr_surf->surface;
-
-   trace_dump_call_begin("pipe_screen", "tex_surface_destroy");
-
-   trace_dump_arg(ptr, screen);
-   trace_dump_arg(ptr, surface);
-
-   trace_dump_call_end();
-
-   trace_surface_destroy(tr_surf);
-}
-
-
-
-
 
 /********************************************************************
  * buffer
@@ -580,8 +521,6 @@
    tr_scr->base.resource_from_handle = trace_screen_resource_from_handle;
    tr_scr->base.resource_get_handle = trace_screen_resource_get_handle;
    tr_scr->base.resource_destroy = trace_screen_resource_destroy;
-   tr_scr->base.get_tex_surface = trace_screen_get_tex_surface;
-   tr_scr->base.tex_surface_destroy = trace_screen_tex_surface_destroy;
    tr_scr->base.user_buffer_create = trace_screen_user_buffer_create;
    tr_scr->base.fence_reference = trace_screen_fence_reference;
    tr_scr->base.fence_signalled = trace_screen_fence_signalled;
diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c
index 9914b98..2799734 100644
--- a/src/gallium/drivers/trace/tr_texture.c
+++ b/src/gallium/drivers/trace/tr_texture.c
@@ -74,8 +74,8 @@
 
 
 struct pipe_surface *
-trace_surface_create(struct trace_resource *tr_tex,
-                     struct pipe_surface *surface)
+trace_surf_create(struct trace_resource *tr_tex,
+                  struct pipe_surface *surface)
 {
    struct trace_surface *tr_surf;
 
@@ -104,7 +104,7 @@
 
 
 void
-trace_surface_destroy(struct trace_surface *tr_surf)
+trace_surf_destroy(struct trace_surface *tr_surf)
 {
    pipe_resource_reference(&tr_surf->base.texture, NULL);
    pipe_surface_reference(&tr_surf->surface, NULL);
diff --git a/src/gallium/drivers/trace/tr_texture.h b/src/gallium/drivers/trace/tr_texture.h
index 6513995..3352c96 100644
--- a/src/gallium/drivers/trace/tr_texture.h
+++ b/src/gallium/drivers/trace/tr_texture.h
@@ -125,11 +125,11 @@
 		       struct trace_resource *tr_tex);
 
 struct pipe_surface *
-trace_surface_create(struct trace_resource *tr_tex,
+trace_surf_create(struct trace_resource *tr_tex,
                      struct pipe_surface *surface);
 
 void
-trace_surface_destroy(struct trace_surface *tr_surf);
+trace_surf_destroy(struct trace_surface *tr_surf);
 
 struct pipe_transfer *
 trace_transfer_create(struct trace_context *tr_ctx,
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 0e53aef..589cac2 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -54,7 +54,6 @@
 struct pipe_shader_state;
 struct pipe_stencil_ref;
 struct pipe_stream_output_state;
-struct pipe_subresource;
 struct pipe_surface;
 struct pipe_vertex_buffer;
 struct pipe_vertex_element;
@@ -256,12 +255,11 @@
     */
    void (*resource_copy_region)(struct pipe_context *pipe,
                                 struct pipe_resource *dst,
-                                struct pipe_subresource subdst,
+                                unsigned dst_level,
                                 unsigned dstx, unsigned dsty, unsigned dstz,
                                 struct pipe_resource *src,
-                                struct pipe_subresource subsrc,
-                                unsigned srcx, unsigned srcy, unsigned srcz,
-                                unsigned width, unsigned height);
+                                unsigned src_level,
+                                const struct pipe_box *src_box);
 
    /**
     * Resolve a multisampled resource into a non-multisampled one.
@@ -269,9 +267,9 @@
     */
    void (*resource_resolve)(struct pipe_context *pipe,
                             struct pipe_resource *dst,
-                            struct pipe_subresource subdst,
+                            unsigned dst_layer,
                             struct pipe_resource *src,
-                            struct pipe_subresource subsrc);
+                            unsigned src_layer);
 
    /*@}*/
 
@@ -328,13 +326,13 @@
     * PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE.
     * \param pipe  context whose unflushed hw commands will be checked.
     * \param texture  texture to check.
-    * \param face  cubemap face. Use 0 for non-cubemap texture.
     * \param level  mipmap level.
+    * \param layer  cubemap face, 2d array or 3d slice, 0 otherwise. Use -1 for any layer.
     * \return mask of PIPE_REFERENCED_FOR_READ/WRITE or PIPE_UNREFERENCED
     */
    unsigned int (*is_resource_referenced)(struct pipe_context *pipe,
-					  struct pipe_resource *texture,
-					  unsigned face, unsigned level);
+                                          struct pipe_resource *texture,
+                                          unsigned level, int layer);
 
    /**
     * Create a view on a texture to be used by a shader stage.
@@ -348,20 +346,32 @@
 
 
    /**
+    * Get a surface which is a "view" into a resource, used by
+    * render target / depth stencil stages.
+    * \param usage  bitmaks of PIPE_BIND_* flags
+    */
+   struct pipe_surface *(*create_surface)(struct pipe_context *ctx,
+                                          struct pipe_resource *resource,
+                                          const struct pipe_surface *templat);
+
+   void (*surface_destroy)(struct pipe_context *ctx,
+                           struct pipe_surface *);
+
+   /**
     * Get a transfer object for transferring data to/from a texture.
     *
     * Transfers are (by default) context-private and allow uploads to be
     * interleaved with
     */
    struct pipe_transfer *(*get_transfer)(struct pipe_context *,
-					 struct pipe_resource *resource,
-					 struct pipe_subresource,
-					 unsigned usage,  /* a combination of PIPE_TRANSFER_x */
-					 const struct pipe_box *);
+                                         struct pipe_resource *resource,
+                                         unsigned level,
+                                         unsigned usage,  /* a combination of PIPE_TRANSFER_x */
+                                         const struct pipe_box *);
 
    void (*transfer_destroy)(struct pipe_context *,
-                                struct pipe_transfer *);
-   
+                            struct pipe_transfer *);
+
    void *(*transfer_map)( struct pipe_context *,
                           struct pipe_transfer *transfer );
 
@@ -381,13 +391,13 @@
     * pointer.  XXX: strides??
     */
    void (*transfer_inline_write)( struct pipe_context *,
-				  struct pipe_resource *,
-				  struct pipe_subresource,
-				  unsigned usage, /* a combination of PIPE_TRANSFER_x */
-				  const struct pipe_box *,
-				  const void *data,
-				  unsigned stride,
-				  unsigned slice_stride);
+                                  struct pipe_resource *,
+                                  unsigned level,
+                                  unsigned usage, /* a combination of PIPE_TRANSFER_x */
+                                  const struct pipe_box *,
+                                  const void *data,
+                                  unsigned stride,
+                                  unsigned layer_stride);
 
 };
 
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index dacabed..f5af15f 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -138,12 +138,14 @@
 /** Texture types.
  * See the documentation for info on PIPE_TEXTURE_RECT vs PIPE_TEXTURE_2D */
 enum pipe_texture_target {
-   PIPE_BUFFER       = 0,
-   PIPE_TEXTURE_1D   = 1,
-   PIPE_TEXTURE_2D   = 2,
-   PIPE_TEXTURE_3D   = 3,
-   PIPE_TEXTURE_CUBE = 4,
-   PIPE_TEXTURE_RECT = 5,
+   PIPE_BUFFER           = 0,
+   PIPE_TEXTURE_1D       = 1,
+   PIPE_TEXTURE_2D       = 2,
+   PIPE_TEXTURE_3D       = 3,
+   PIPE_TEXTURE_CUBE     = 4,
+   PIPE_TEXTURE_RECT     = 5,
+   PIPE_TEXTURE_1D_ARRAY = 6,
+   PIPE_TEXTURE_2D_ARRAY = 7,
    PIPE_MAX_TEXTURE_TYPES
 };
 
@@ -178,14 +180,6 @@
 #define PIPE_TEX_COMPARE_NONE          0
 #define PIPE_TEX_COMPARE_R_TO_TEXTURE  1
 
-
-/**
- * Surface layout -- a hint?  Or some driver-internal poking out into
- * the interface?
- */
-#define PIPE_SURFACE_LAYOUT_LINEAR  0
-
-
 /**
  * Clear buffer bits
  */
@@ -281,9 +275,9 @@
  * Resource binding flags -- state tracker must specify in advance all
  * the ways a resource might be used.
  */
-#define PIPE_BIND_DEPTH_STENCIL        (1 << 0) /* get_tex_surface */
-#define PIPE_BIND_RENDER_TARGET        (1 << 1) /* get_tex_surface */
-#define PIPE_BIND_SAMPLER_VIEW         (1 << 2) /* get_sampler_view */
+#define PIPE_BIND_DEPTH_STENCIL        (1 << 0) /* create_surface */
+#define PIPE_BIND_RENDER_TARGET        (1 << 1) /* create_surface */
+#define PIPE_BIND_SAMPLER_VIEW         (1 << 2) /* create_sampler_view */
 #define PIPE_BIND_VERTEX_BUFFER        (1 << 3) /* set_vertex_buffers */
 #define PIPE_BIND_INDEX_BUFFER         (1 << 4) /* draw_elements */
 #define PIPE_BIND_CONSTANT_BUFFER      (1 << 5) /* set_constant_buffer */
@@ -461,6 +455,7 @@
    /** different blend funcs per rendertarget */
    PIPE_CAP_INDEP_BLEND_FUNC,
    PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE,
+   PIPE_CAP_ARRAY_TEXTURES,
    PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT,
    PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT,
    PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER,
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
index 9126312..850eb84 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -117,7 +117,7 @@
    /**
     * Create a texture from a winsys_handle. The handle is often created in
     * another process by first creating a pipe texture and then calling
-    * texture_get_handle.
+    * resource_get_handle.
     */
    struct pipe_resource * (*resource_from_handle)(struct pipe_screen *,
 						  const struct pipe_resource *templat,
@@ -136,18 +136,6 @@
    void (*resource_destroy)(struct pipe_screen *,
 			    struct pipe_resource *pt);
 
-   /** Get a 2D surface which is a "view" into a texture
-    * \param usage  bitmaks of PIPE_BIND_* flags
-    */
-   struct pipe_surface *(*get_tex_surface)(struct pipe_screen *,
-                                           struct pipe_resource *resource,
-                                           unsigned face, unsigned level,
-                                           unsigned zslice,
-                                           unsigned usage );
-
-   void (*tex_surface_destroy)(struct pipe_surface *);
-   
-
 
    /**
     * Create a buffer that wraps user-space data.
@@ -182,7 +170,8 @@
     *                                gets out-of-band
     */
    void (*flush_frontbuffer)( struct pipe_screen *screen,
-                              struct pipe_surface *surf,
+                              struct pipe_resource *resource,
+                              unsigned level, unsigned layer,
                               void *winsys_drawable_handle );
 
 
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index fc6dba3..226ae86 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -271,25 +271,33 @@
 
 
 /**
- * 2D surface.  This is basically a view into a memory buffer.
- * May be a renderbuffer, texture mipmap level, etc.
+ * A view into a texture that can be bound to a color render target /
+ * depth stencil attachment point.
  */
 struct pipe_surface
 {
    struct pipe_reference reference;
    struct pipe_resource *texture; /**< resource into which this is a view  */
+   struct pipe_context *context; /**< context this view belongs to */
    enum pipe_format format;
 
+   /* XXX width/height should be removed */
    unsigned width;               /**< logical width in pixels */
    unsigned height;              /**< logical height in pixels */
 
-   unsigned layout;              /**< PIPE_SURFACE_LAYOUT_x */
-   unsigned offset;              /**< offset from start of buffer, in bytes */
    unsigned usage;               /**< bitmask of PIPE_BIND_x */
 
-   unsigned zslice;
-   unsigned face;
-   unsigned level;
+   union {
+      struct {
+         unsigned level;
+         unsigned first_layer:16;
+         unsigned last_layer:16;
+      } tex;
+      struct {
+         unsigned first_element;
+         unsigned last_element;
+      } buf;
+   } u;
 };
 
 
@@ -302,8 +310,18 @@
    enum pipe_format format;      /**< typed PIPE_FORMAT_x */
    struct pipe_resource *texture; /**< texture into which this is a view  */
    struct pipe_context *context; /**< context this view belongs to */
-   unsigned first_level:8;       /**< first mipmap level */
-   unsigned last_level:8;        /**< last mipmap level */
+   union {
+      struct {
+         unsigned first_layer:16;     /**< first layer to use for array textures */
+         unsigned last_layer:16;      /**< last layer to use for array textures */
+         unsigned first_level:8;      /**< first mipmap level to use */
+         unsigned last_level:8;       /**< last mipmap level to use */
+      } tex;
+      struct {
+         unsigned first_element;
+         unsigned last_element;
+      } buf;
+   } u;
    unsigned swizzle_r:3;         /**< PIPE_SWIZZLE_x for red component */
    unsigned swizzle_g:3;         /**< PIPE_SWIZZLE_x for green component */
    unsigned swizzle_b:3;         /**< PIPE_SWIZZLE_x for blue component */
@@ -338,13 +356,14 @@
    unsigned width0;
    unsigned height0;
    unsigned depth0;
+   unsigned array_size;
 
    unsigned last_level:8;    /**< Index of last mipmap level present/defined */
    unsigned nr_samples:8;    /**< for multisampled surfaces, nr of samples */
    unsigned usage:8;         /**< PIPE_USAGE_x (not a bitmask) */
 
-   unsigned bind;	     /**< bitmask of PIPE_BIND_x */
-   unsigned flags;	     /**< bitmask of PIPE_RESOURCE_FLAG_x */
+   unsigned bind;            /**< bitmask of PIPE_BIND_x */
+   unsigned flags;           /**< bitmask of PIPE_RESOURCE_FLAG_x */
 };
 
 struct pipe_stream_output_state
@@ -363,15 +382,6 @@
    unsigned stride;
 };
 
-/**
- * Extra indexing info for (cube) texture resources.
- */
-struct pipe_subresource
-{
-   unsigned face:16;
-   unsigned level:16;
-};
-
 
 /**
  * Transfer object.  For data transfer to/from a resource.
@@ -379,11 +389,11 @@
 struct pipe_transfer
 {
    struct pipe_resource *resource; /**< resource to transfer to/from  */
-   struct pipe_subresource sr;
+   unsigned level;
    enum pipe_transfer_usage usage;
    struct pipe_box box;
    unsigned stride;
-   unsigned slice_stride;
+   unsigned layer_stride;
    void *data;
 };
 
diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
index 565a096..1c2148b 100644
--- a/src/gallium/include/state_tracker/st_api.h
+++ b/src/gallium/include/state_tracker/st_api.h
@@ -164,9 +164,8 @@
    /* this is owned by the caller */
    struct pipe_resource *texture;
 
-   unsigned face;
    unsigned level;
-   unsigned zslice;
+   unsigned layer;
 };
 
 /**
diff --git a/src/gallium/include/state_tracker/xlib_sw_winsys.h b/src/gallium/include/state_tracker/xlib_sw_winsys.h
index f22c22b..4e7ccc1 100644
--- a/src/gallium/include/state_tracker/xlib_sw_winsys.h
+++ b/src/gallium/include/state_tracker/xlib_sw_winsys.h
@@ -6,7 +6,7 @@
 
 
 struct pipe_screen;
-struct pipe_surface;
+struct pipe_resource;
 
 /* This is what the xlib software winsys expects to find in the
  * "private" field of flush_frontbuffers().
diff --git a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
index c246fc5..a54324a 100644
--- a/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
+++ b/src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp
@@ -1159,8 +1159,15 @@
 			unsigned blit_x, blit_y, blit_w, blit_h;
 			float black[4] = {0, 0, 0, 0};
 
-			if(!formats_compatible || src->width0 != dst_w || src->height0 != dst_h)
-				dst_surface = pipe->screen->get_tex_surface(pipe->screen, dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+			if(!formats_compatible || src->width0 != dst_w || src->height0 != dst_h) {
+				struct pipe_surface templat;
+				templat.usage = PIPE_BIND_RENDER_TARGET;
+				templat.format = dst->format;
+				templat.u.tex.level = 0;
+				templat.u.tex.first_layer = 0;
+				templat.u.tex.last_layer = 0;
+				dst_surface = pipe->create_surface(pipe, dst, &templat);
+			}
 
 			if(preserve_aspect_ratio)
 			{
@@ -1199,10 +1206,12 @@
 
 			if(formats_compatible && blit_w == src->width0 && blit_h == src->height0)
 			{
-				pipe_subresource sr;
-				sr.face = 0;
-				sr.level = 0;
-				pipe->resource_copy_region(pipe, dst, sr, rect.left, rect.top, 0, src, sr, 0, 0, 0, blit_w, blit_h);
+				pipe_box box;
+				box.x = box.y = box.z;
+				box.width = blit_w;
+				box.height = blit_h;
+				box.z = 1;
+				pipe->resource_copy_region(pipe, dst, 0, rect.left, rect.top, 0, src, 0, &box);
 			}
 			else
 			{
@@ -1218,7 +1227,7 @@
 		}
 
 		if(dst_surface)
-			pipe->screen->tex_surface_destroy(dst_surface);
+			pipe->surface_destroy(pipe, dst_surface);
 
 		pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, 0);
 
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
index 3611059..e1ba6c1 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
@@ -1416,23 +1416,33 @@
 			*out_predicate_value = render_predicate_value;
 	}
 
-	static pipe_subresource d3d11_to_pipe_subresource(struct pipe_resource* resource, unsigned subresource)
+	static unsigned d3d11_subresource_to_level(struct pipe_resource* resource, unsigned subresource)
 	{
-		pipe_subresource sr;
 		if(subresource <= resource->last_level)
 		{
-			sr.level = subresource;
-			sr.face = 0;
+			return subresource;
 		}
 		else
 		{
 			unsigned levels = resource->last_level + 1;
-			sr.level = subresource % levels;
-			sr.face = subresource / levels;
+			return subresource % levels;
 		}
-		return sr;
 	}
 
+	static unsigned d3d11_subresource_to_face(struct pipe_resource* resource, unsigned subresource)
+	{
+		if(subresource <= resource->last_level)
+		{
+			return 0;
+		}
+		else
+		{
+			unsigned levels = resource->last_level + 1;
+			return subresource / levels;
+		}
+	}
+		
+	
 	/* TODO: deferred contexts will need a different implementation of this,
 	 * because we can't put the transfer info into the resource itself.
 	 * Also, there are very different restrictions, for obvious reasons.
@@ -1448,8 +1458,10 @@
 		GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource;
 		if(resource->transfers.count(subresource))
 			return E_FAIL;
-		pipe_subresource sr = d3d11_to_pipe_subresource(resource->resource, subresource);
-		pipe_box box = d3d11_to_pipe_box(resource->resource, sr.level, 0);
+		unsigned level = d3d11_subresource_to_level(resource->resource, subresource);
+		unsigned face = d3d11_subresource_to_face(resource->resource, subresource);
+		pipe_box box = d3d11_to_pipe_box(resource->resource, level, 0);
+		/* XXX the translation from subresource to level/face(zslice/array layer) isn't quite right */
 		unsigned usage = 0;
 		if(map_type == D3D11_MAP_READ)
 			usage = PIPE_TRANSFER_READ;
@@ -1465,7 +1477,7 @@
 			return E_INVALIDARG;
 		if(map_type & D3D10_MAP_FLAG_DO_NOT_WAIT)
 			usage |= PIPE_TRANSFER_DONTBLOCK;
-		struct pipe_transfer* transfer = pipe->get_transfer(pipe, resource->resource, sr, usage, &box);
+		struct pipe_transfer* transfer = pipe->get_transfer(pipe, resource->resource, level, usage, &box);
 		if(!transfer) {
 			if(map_type & D3D10_MAP_FLAG_DO_NOT_WAIT)
 				return DXGI_ERROR_WAS_STILL_DRAWING;
@@ -1475,7 +1487,7 @@
 		resource->transfers[subresource] = transfer;
 		mapped_resource->pData = pipe->transfer_map(pipe, transfer);
 		mapped_resource->RowPitch = transfer->stride;
-		mapped_resource->DepthPitch = transfer->slice_stride;
+		mapped_resource->DepthPitch = transfer->layer_stride;
 		return S_OK;
 	}
 
@@ -1507,15 +1519,16 @@
 		SYNCHRONIZED;
 		GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
 		GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource;
-		pipe_subresource subdst = d3d11_to_pipe_subresource(dst->resource, dst_subresource);
-		pipe_subresource subsrc = d3d11_to_pipe_subresource(src->resource, src_subresource);
-		pipe_box box = d3d11_to_pipe_box(src->resource, subsrc.level, src_box);
-		for(unsigned i = 0; i < box.depth; ++i)
+		unsigned dst_level = d3d11_subresource_to_level(dst->resource, dst_subresource);
+		unsigned dst_face = d3d11_subresource_to_face(dst->resource, dst_subresource);
+		unsigned src_level = d3d11_subresource_to_level(src->resource, src_subresource);
+		unsigned src_face = d3d11_subresource_to_face(src->resource, src_subresource);
+		/* XXX the translation from subresource to level/face(zslice/array layer) isn't quite right */
+		pipe_box box = d3d11_to_pipe_box(src->resource, src_level, src_box);
 		{
 			pipe->resource_copy_region(pipe,
-				dst->resource, subdst, dst_x, dst_y, dst_z + i,
-				src->resource, subsrc, box.x, box.y, box.z + i,
-				box.width, box.height);
+				dst->resource, dst_level, dst_x, dst_y, dst_z,
+				src->resource, src_level, &box);
 		}
 	}
 
@@ -1526,24 +1539,23 @@
 		SYNCHRONIZED;
 		GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
 		GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource;
-		pipe_subresource sr;
-		unsigned faces = dst->resource->target == PIPE_TEXTURE_CUBE ? 6 : 1;
-
-		for(sr.face = 0; sr.face < faces; ++sr.face)
+		unsigned level;
+		for(level = 0; level <= dst->resource->last_level; ++level)
 		{
-			for(sr.level = 0; sr.level <= dst->resource->last_level; ++sr.level)
-			{
-				unsigned w = u_minify(dst->resource->width0, sr.level);
-				unsigned h = u_minify(dst->resource->height0, sr.level);
-				unsigned d = u_minify(dst->resource->depth0, sr.level);
-				for(unsigned i = 0; i < d; ++i)
-				{
-					pipe->resource_copy_region(pipe,
-							dst->resource, sr, 0, 0, i,
-							src->resource, sr, 0, 0, i,
-							w, h);
-				}
-			}
+		        unsigned layers = 1;
+			pipe_box box;
+			if (dst->resource->target == PIPE_TEXTURE_CUBE)
+				layers = 6;
+			else if (dst->resource->target == PIPE_TEXTURE_3D)
+				layers = u_minify(dst->resource->depth0, level);
+			/* else layers = dst->resource->array_size; */
+			box.x = box.y = box.z = 0;
+			box.width = u_minify(dst->resource->width0, level);
+			box.height = u_minify(dst->resource->height0, level);
+			box.depth = layers;
+			pipe->resource_copy_region(pipe,
+						   dst->resource, level, 0, 0, 0,
+						   src->resource, level, &box);
 		}
 	}
 
@@ -1557,9 +1569,10 @@
 	{
 		SYNCHRONIZED;
 		GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
-		pipe_subresource subdst = d3d11_to_pipe_subresource(dst->resource, dst_subresource);
-		pipe_box box = d3d11_to_pipe_box(dst->resource, subdst.level, pDstBox);
-		pipe->transfer_inline_write(pipe, dst->resource, subdst, PIPE_TRANSFER_WRITE, &box, pSrcData, src_row_pitch, src_depth_pitch);
+		unsigned dst_level = d3d11_subresource_to_level(dst->resource, dst_subresource);
+		/* XXX the translation from subresource to level/face(zslice/array layer) isn't quite right */
+		pipe_box box = d3d11_to_pipe_box(dst->resource, dst_level, pDstBox);
+		pipe->transfer_inline_write(pipe, dst->resource, dst_level, PIPE_TRANSFER_WRITE, &box, pSrcData, src_row_pitch, src_depth_pitch);
 	}
 
 #if API >= 11
@@ -1714,9 +1727,9 @@
 		SYNCHRONIZED;
 		GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
 		GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource;
-		pipe_subresource subdst = d3d11_to_pipe_subresource(dst->resource, dst_subresource);
-		pipe_subresource subsrc = d3d11_to_pipe_subresource(src->resource, src_subresource);
-		pipe->resource_resolve(pipe, dst->resource, subdst, src->resource, subsrc);
+		unsigned dst_layer = d3d11_subresource_to_face(dst->resource, dst_subresource);
+		unsigned src_layer = d3d11_subresource_to_face(src->resource, src_subresource);
+		pipe->resource_resolve(pipe, dst->resource, dst_layer, src->resource, src_layer);
 	}
 
 #if API >= 11
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
index 95ea4e0..9cfdc83 100644
--- a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
@@ -718,15 +718,13 @@
 			{
 				for(unsigned level = 0; level <= templat.last_level; ++level)
 				{
-					struct pipe_subresource sr;
-					sr.level = level;
-					sr.face = slice;
 					struct pipe_box box;
-					box.x = box.y = box.z = 0;
+					box.x = box.y = 0;
+					box.z = slice;
 					box.width = u_minify(width, level);
 					box.height = u_minify(height, level);
-					box.depth = u_minify(depth, level);
-					immediate_pipe->transfer_inline_write(immediate_pipe, resource, sr, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, initial_data->pSysMem, initial_data->SysMemPitch, initial_data->SysMemSlicePitch);
+					box.depth = 1;
+					immediate_pipe->transfer_inline_write(immediate_pipe, resource, level, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, initial_data->pSysMem, initial_data->SysMemPitch, initial_data->SysMemSlicePitch);
 					++initial_data;
 				}
 			}
@@ -978,8 +976,8 @@
 		case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
 		case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
 			/* yes, this works for all of these types (but TODO: texture arrays) */
-			templat.first_level = desc->Texture1D.MostDetailedMip;
-			templat.last_level = templat.first_level + desc->Texture1D.MipLevels - 1;
+			templat.u.tex.first_level = desc->Texture1D.MostDetailedMip;
+			templat.u.tex.last_level = templat.u.tex.first_level + desc->Texture1D.MipLevels - 1;
 			break;
 		case D3D11_SRV_DIMENSION_BUFFER:
 		case D3D11_SRV_DIMENSION_TEXTURE2DMS:
@@ -1054,30 +1052,34 @@
 			desc = &def_desc;
 		}
 
-		unsigned zslice = 0;
-		unsigned face = 0;
-		unsigned level;
-		enum pipe_format format;
+		struct pipe_surface templat;
+		memset(&templat, 0, sizeof(templat));
 		if(invalid(desc->format >= DXGI_FORMAT_COUNT))
 			return E_INVALIDARG;
-		format = dxgi_to_pipe_format[desc->Format];
-		if(!format)
+		templat.format = dxgi_to_pipe_format[desc->Format];
+		if(!templat.format)
 			return E_NOTIMPL;
+		templat.usage = PIPE_BIND_RENDER_TARGET;
+		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
 
 		switch(desc->ViewDimension)
 		{
 		case D3D11_RTV_DIMENSION_TEXTURE1D:
 		case D3D11_RTV_DIMENSION_TEXTURE2D:
-			level = desc->Texture1D.MipSlice;
+			templat.u.tex.level = desc->Texture1D.MipSlice;
 			break;
 		case D3D11_RTV_DIMENSION_TEXTURE3D:
-			level = desc->Texture3D.MipSlice;
-			zslice = desc->Texture3D.FirstWSlice;
+			templat.u.tex.level = desc->Texture3D.MipSlice;
+			templat.u.tex.first_layer = desc->Texture3D.FirstWSlice;
+			/* XXX FIXME */
+			templat.u.tex.last_layer = desc->Texture3D.FirstWSlice;
 			break;
 		case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
 		case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
-			level = desc->Texture1DArray.MipSlice;
-			face = desc->Texture1DArray.FirstArraySlice;
+			templat.u.tex.level = desc->Texture1DArray.MipSlice;
+			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
+			/* XXX FIXME */
+			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice;
 			break;
 		case D3D11_RTV_DIMENSION_BUFFER:
 		case D3D11_RTV_DIMENSION_TEXTURE2DMS:
@@ -1090,13 +1092,9 @@
 		if(!out_rtv)
 			return S_FALSE;
 
-		struct pipe_surface* surface = screen->get_tex_surface(screen,
-				((GalliumD3D11Resource<>*)iresource)->resource,
-				face, level, zslice, PIPE_BIND_RENDER_TARGET);
+		struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
 		if(!surface)
 			return E_FAIL;
-		/* muhahahahaha, let's hope this actually works */
-		surface->format = format;
 		*out_rtv = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
 		return S_OK;
 	}
@@ -1134,26 +1132,28 @@
 			desc = &def_desc;
 		}
 
-		unsigned zslice = 0;
-		unsigned face = 0;
-		unsigned level;
-		enum pipe_format format;
+		struct pipe_surface templat;
+		memset(&templat, 0, sizeof(templat));
 		if(invalid(desc->format >= DXGI_FORMAT_COUNT))
 			return E_INVALIDARG;
-		format = dxgi_to_pipe_format[desc->Format];
-		if(!format)
+		templat.format = dxgi_to_pipe_format[desc->Format];
+		if(!templat.format)
 			return E_NOTIMPL;
+		templat.usage = PIPE_BIND_DEPTH_STENCIL;
+		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
 
 		switch(desc->ViewDimension)
 		{
 		case D3D11_DSV_DIMENSION_TEXTURE1D:
 		case D3D11_DSV_DIMENSION_TEXTURE2D:
-			level = desc->Texture1D.MipSlice;
+			templat.u.tex.level = desc->Texture1D.MipSlice;
 			break;
 		case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
 		case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
-			level = desc->Texture1DArray.MipSlice;
-			face = desc->Texture1DArray.FirstArraySlice;
+			templat.u.tex.level = desc->Texture1DArray.MipSlice;
+			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
+			/* XXX FIXME */
+			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice;
 			break;
 		case D3D11_DSV_DIMENSION_TEXTURE2DMS:
 		case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
@@ -1165,13 +1165,9 @@
 		if(!out_depth_stencil_view)
 			return S_FALSE;
 
-		struct pipe_surface* surface = screen->get_tex_surface(screen,
-				((GalliumD3D11Resource<>*)iresource)->resource,
-				face, level, zslice, PIPE_BIND_DEPTH_STENCIL);
+		struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
 		if(!surface)
 			return E_FAIL;
-		/* muhahahahaha, let's hope this actually works */
-		surface->format = format;
 		*out_depth_stencil_view = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
 		return S_OK;
 	}
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c
index 1302e9b..f6e22c7 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.c
+++ b/src/gallium/state_trackers/dri/common/dri_screen.c
@@ -304,9 +304,8 @@
 
    stimg->texture = NULL;
    pipe_resource_reference(&stimg->texture, img->texture);
-   stimg->face = img->face;
    stimg->level = img->level;
-   stimg->zslice = img->zslice;
+   stimg->layer = img->layer;
 
    return TRUE;
 }
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.h b/src/gallium/state_trackers/dri/common/dri_screen.h
index 0da9b55..8cb0a10 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.h
+++ b/src/gallium/state_trackers/dri/common/dri_screen.h
@@ -83,9 +83,8 @@
 
 struct __DRIimageRec {
    struct pipe_resource *texture;
-   unsigned face;
    unsigned level;
-   unsigned zslice;
+   unsigned layer;
 
    void *loader_private;
 };
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index 3c5b075..a9d05a8 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -200,6 +200,7 @@
    templ.width0 = dri_drawable->w;
    templ.height0 = dri_drawable->h;
    templ.depth0 = 1;
+   templ.array_size = 1;
 
    memset(&whandle, 0, sizeof(whandle));
 
@@ -348,6 +349,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
 
    memset(&whandle, 0, sizeof(whandle));
    whandle.handle = name;
@@ -360,9 +362,8 @@
       return NULL;
    }
 
-   img->face = 0;
    img->level = 0;
-   img->zslice = 0;
+   img->layer = 0;
    img->loader_private = loaderPrivate;
 
    return img;
@@ -430,9 +431,8 @@
       return NULL;
    }
 
-   img->face = 0;
    img->level = 0;
-   img->zslice = 0;
+   img->layer = 0;
 
    img->loader_private = loaderPrivate;
    return img;
diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c
index c48cc44..30088b0 100644
--- a/src/gallium/state_trackers/dri/sw/drisw.c
+++ b/src/gallium/state_trackers/dri/sw/drisw.c
@@ -87,40 +87,17 @@
    put_image(dPriv, data, width, height);
 }
 
-static struct pipe_surface *
-drisw_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex)
-{
-   struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->base.screen;
-   struct pipe_surface *psurf = drawable->drisw_surface;
-
-   if (!psurf || psurf->texture != ptex) {
-      pipe_surface_reference(&drawable->drisw_surface, NULL);
-
-      drawable->drisw_surface = pipe_screen->get_tex_surface(pipe_screen,
-            ptex, 0, 0, 0, 0/* no bind flag???*/);
-
-      psurf = drawable->drisw_surface;
-   }
-
-   return psurf;
-}
-
 static INLINE void
 drisw_present_texture(__DRIdrawable *dPriv,
                       struct pipe_resource *ptex)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
    struct dri_screen *screen = dri_screen(drawable->sPriv);
-   struct pipe_surface *psurf;
 
    if (swrast_no_present)
       return;
 
-   psurf = drisw_get_pipe_surface(drawable, ptex);
-   if (!psurf)
-      return;
-
-   screen->base.screen->flush_frontbuffer(screen->base.screen, psurf, drawable);
+   screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable);
 }
 
 static INLINE void
@@ -220,6 +197,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
 
    for (i = 0; i < count; i++) {
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
index 72c14f0..9873fee 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
@@ -92,9 +92,8 @@
 struct egl_g3d_image {
    _EGLImage base;
    struct pipe_resource *texture;
-   unsigned face;
    unsigned level;
-   unsigned zslice;
+   unsigned layer;
 };
 
 /* standard typecasts */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
index fd7dc8f..f505220 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
@@ -30,6 +30,7 @@
 #include "pipe/p_screen.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
+#include "util/u_box.h"
 
 #include "egl_g3d.h"
 #include "egl_g3d_api.h"
@@ -665,15 +666,11 @@
    ptex = get_pipe_resource(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
    if (ptex) {
       struct pipe_resource *psrc = gsurf->render_texture;
-      struct pipe_subresource subsrc, subdst;
-      subsrc.face = 0;
-      subsrc.level = 0;
-      subdst.face = 0;
-      subdst.level = 0;
-
+      struct pipe_box src_box;
+      u_box_origin_2d(ptex->width0, ptex->height0, &src_box);
       if (psrc) {
-         gdpy->pipe->resource_copy_region(gdpy->pipe, ptex, subdst, 0, 0, 0,
-               gsurf->render_texture, subsrc, 0, 0, 0, ptex->width0, ptex->height0);
+         gdpy->pipe->resource_copy_region(gdpy->pipe, ptex, 0, 0, 0, 0,
+               gsurf->render_texture, 0, &src_box);
          nsurf->present(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0);
       }
 
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
index 6a1f8cc..38627a5 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -191,7 +191,7 @@
 {
    struct pipe_resource *ptex;
    struct egl_g3d_image *gimg;
-   unsigned face = 0, level = 0, zslice = 0;
+   unsigned level = 0, layer = 0;
 
    gimg = CALLOC_STRUCT(egl_g3d_image);
    if (!gimg) {
@@ -231,7 +231,7 @@
       FREE(gimg);
       return NULL;
    }
-   if (zslice > ptex->depth0) {
+   if (layer >= (u_minify(ptex->depth0, level) + ptex->array_size - 1)) {
       _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
       pipe_resource_reference(&gimg->texture, NULL);
       FREE(gimg);
@@ -240,9 +240,8 @@
 
    /* transfer the ownership to the image */
    gimg->texture = ptex;
-   gimg->face = face;
    gimg->level = level;
-   gimg->zslice = zslice;
+   gimg->layer = layer;
 
    return &gimg->base;
 }
@@ -288,9 +287,8 @@
 
    /* transfer the ownership to the image */
    gimg->texture = ptex;
-   gimg->face = 0;
    gimg->level = 0;
-   gimg->zslice = 0;
+   gimg->layer = 0;
 
    return &gimg->base;
 }
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
index 25e2999..2b944b5 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
@@ -72,9 +72,8 @@
 
    out->texture = NULL;
    pipe_resource_reference(&out->texture, gimg->texture);
-   out->face = gimg->face;
    out->level = gimg->level;
-   out->zslice = gimg->zslice;
+   out->layer = gimg->layer;
 
    _eglUnlockMutex(&gsmapi->display->Mutex);
 
@@ -140,6 +139,7 @@
    templ.width0 = gsurf->base.Width;
    templ.height0 = gsurf->base.Height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.format = gsurf->stvis.color_format;
    templ.bind = PIPE_BIND_RENDER_TARGET;
 
diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c
index 7832b2b..0f2d020 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.c
+++ b/src/gallium/state_trackers/egl/common/native_helper.c
@@ -40,7 +40,6 @@
    uint bind;
 
    struct pipe_resource *resources[NUM_NATIVE_ATTACHMENTS];
-   struct pipe_surface *present_surfaces[NUM_NATIVE_ATTACHMENTS];
    uint resource_mask;
    uint width, height;
 };
@@ -67,8 +66,6 @@
       int i;
 
       for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
-         if (rsurf->present_surfaces[i])
-            pipe_surface_reference(&rsurf->present_surfaces[i], NULL);
          if (rsurf->resources[i])
             pipe_resource_reference(&rsurf->resources[i], NULL);
       }
@@ -130,6 +127,7 @@
    templ.width0 = rsurf->width;
    templ.height0 = rsurf->height;
    templ.depth0 = 1;
+   templ.array_size = 1;
 
    for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
       if (resource_mask & (1 <<i)) {
@@ -193,8 +191,6 @@
 
    pointer_swap((const void **) &rsurf->resources[buf1],
                 (const void **) &rsurf->resources[buf2]);
-   pointer_swap((const void **) &rsurf->present_surfaces[buf1],
-                (const void **) &rsurf->present_surfaces[buf2]);
 
    /* swap mask bits */
    mask = rsurf->resource_mask & ~(buf1_bit | buf2_bit);
@@ -212,24 +208,12 @@
                          void *winsys_drawable_handle)
 {
    struct pipe_resource *pres = rsurf->resources[which];
-   struct pipe_surface *psurf = rsurf->present_surfaces[which];
 
    if (!pres)
       return TRUE;
 
-   if (!psurf) {
-      psurf = rsurf->screen->get_tex_surface(rsurf->screen,
-            pres, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET);
-      if (!psurf)
-         return FALSE;
-
-      rsurf->present_surfaces[which] = psurf;
-   }
-
-   assert(psurf->texture == pres);
-
    rsurf->screen->flush_frontbuffer(rsurf->screen,
-         psurf, winsys_drawable_handle);
+         pres, 0, 0, winsys_drawable_handle);
 
    return TRUE;
 }
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index 331a7de..8108ce4 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -136,6 +136,7 @@
    templ.width0 = dri2surf->width;
    templ.height0 = dri2surf->height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.format = dri2surf->color_format;
    templ.bind = PIPE_BIND_RENDER_TARGET;
 
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c
index e7466bd..6bfe8b0 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_st.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_st.c
@@ -42,7 +42,7 @@
    unsigned texture_width, texture_height, texture_mask;
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
 
-   struct pipe_surface *display_surface;
+   struct pipe_resource *display_resource;
 };
 
 static INLINE struct xmesa_st_framebuffer *
@@ -60,25 +60,19 @@
 {
    struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
    struct pipe_resource *ptex = xstfb->textures[statt];
-   struct pipe_surface *psurf;
+   struct pipe_resource *pres;
 
    if (!ptex)
       return TRUE;
 
-   psurf = xstfb->display_surface;
+   pres = xstfb->display_resource;
    /* (re)allocate the surface for the texture to be displayed */
-   if (!psurf || psurf->texture != ptex) {
-      pipe_surface_reference(&xstfb->display_surface, NULL);
-
-      psurf = xstfb->screen->get_tex_surface(xstfb->screen,
-            ptex, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET);
-      if (!psurf)
-         return FALSE;
-
-      xstfb->display_surface = psurf;
+   if (!pres || pres != ptex) {
+      pipe_resource_reference(&xstfb->display_resource, ptex);
+      pres = xstfb->display_resource;
    }
 
-   xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws);
+   xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws);
 
    return TRUE;
 }
@@ -96,7 +90,7 @@
    struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
    struct pipe_resource *src_ptex = xstfb->textures[src_statt];
    struct pipe_resource *dst_ptex = xstfb->textures[dst_statt];
-   struct pipe_subresource subsrc, subdst;
+   struct pipe_box src_box;
    struct pipe_context *pipe;
 
    if (!src_ptex || !dst_ptex)
@@ -110,14 +104,11 @@
       xstfb->display->pipe = pipe;
    }
 
-   subsrc.face = 0;
-   subsrc.level = 0;
-   subdst.face = 0;
-   subdst.level = 0;
+   u_box_2d(x, y, width, height, &src_box);
 
    if (src_ptex && dst_ptex)
-      pipe->resource_copy_region(pipe, dst_ptex, subdst, x, y, 0,
-                                 src_ptex, subsrc, x, y, 0, width, height);
+      pipe->resource_copy_region(pipe, dst_ptex, 0, x, y, 0,
+                                 src_ptex, 0, &src_box);
 }
 
 /**
@@ -144,6 +135,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
@@ -321,7 +313,7 @@
    struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
    int i;
 
-   pipe_surface_reference(&xstfb->display_surface, NULL);
+   pipe_resource_reference(&xstfb->display_resource, NULL);
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
       pipe_resource_reference(&xstfb->textures[i], NULL);
diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i
index 40c4603..5bdeaa8 100644
--- a/src/gallium/state_trackers/python/p_context.i
+++ b/src/gallium/state_trackers/python/p_context.i
@@ -132,6 +132,8 @@
                        enum pipe_format format = PIPE_FORMAT_NONE,
                        unsigned first_level = 0,
                        unsigned last_level = ~0,
+                       unsigned first_layer = 0,
+                       unsigned last_layer = ~0,
                        unsigned swizzle_r = 0,
                        unsigned swizzle_g = 1,
                        unsigned swizzle_b = 2,
@@ -146,9 +148,10 @@
       } else {
          templat.format = format;
       }
-      templat.last_level = MIN2(last_level, texture->last_level);
-      templat.first_level = first_level;
-      templat.last_level = last_level;
+      templat.u.tex.last_level = MIN2(last_level, texture->last_level);
+      templat.u.tex.first_level = first_level;
+      templat.u.tex.first_layer = first_layer;
+      templat.u.tex.last_layer = last_layer;
       templat.swizzle_r = swizzle_r;
       templat.swizzle_g = swizzle_g;
       templat.swizzle_b = swizzle_b;
@@ -412,17 +415,15 @@
     */
 
    void resource_copy_region(struct pipe_resource *dst,
-                             struct pipe_subresource subdst,
+                             unsigned dst_level,
                              unsigned dstx, unsigned dsty, unsigned dstz,
                              struct pipe_resource *src,
-                             struct pipe_subresource subsrc,
-                             unsigned srcx, unsigned srcy, unsigned srcz,
-                             unsigned width, unsigned height)
+                             unsigned src_level,
+                             const struct pipe_box *src_box)
    {
       $self->pipe->resource_copy_region($self->pipe,
-                                        dst, subdst, dstx, dsty, dstz,
-                                        src, subsrc, srcx, srcy, srcz,
-                                        width, height);
+                                        dst, dst_level, dstx, dsty, dstz,
+                                        src, src_level, src_box);
    }
 
 
@@ -433,7 +434,7 @@
    {
       struct pipe_surface *_dst = NULL;
 
-     _dst = st_pipe_surface(dst, PIPE_BIND_RENDER_TARGET);
+     _dst = st_pipe_surface($self->pipe, dst, PIPE_BIND_RENDER_TARGET);
       if(!_dst)
          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
 
@@ -452,7 +453,7 @@
    {
       struct pipe_surface *_dst = NULL;
 
-     _dst = st_pipe_surface(dst, PIPE_BIND_DEPTH_STENCIL);
+     _dst = st_pipe_surface($self->pipe, dst, PIPE_BIND_DEPTH_STENCIL);
       if(!_dst)
          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
 
@@ -482,9 +483,8 @@
 
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_READ,
                                    x, y, w, h);
       if(transfer) {
@@ -511,9 +511,8 @@
 
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_WRITE,
                                    x, y, w, h);
       if(!transfer)
@@ -535,9 +534,8 @@
       struct pipe_transfer *transfer;
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_READ,
                                    x, y, w, h);
       if(transfer) {
@@ -555,9 +553,8 @@
       struct pipe_transfer *transfer;
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_WRITE,
                                    x, y, w, h);
       if(transfer) {
@@ -597,9 +594,8 @@
 
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_READ,
                                    x, y, w, h);
       if(transfer) {
@@ -624,9 +620,8 @@
       struct pipe_transfer *transfer;
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_READ,
                                    x, y, w, h);
       if(transfer) {
@@ -644,9 +639,8 @@
       struct pipe_transfer *transfer;
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_WRITE,
                                    x, y, w, h);
       if(transfer) {
@@ -681,9 +675,8 @@
 
       transfer = pipe_get_transfer(pipe,
                                    surface->texture,
-                                   surface->face,
                                    surface->level,
-                                   surface->zslice,
+                                   surface->layer,
                                    PIPE_TRANSFER_READ,
                                    x, y, w, h);
       if(!transfer) {
@@ -715,16 +708,16 @@
    %cstring_input_binary(const char *STRING, unsigned LENGTH);
    void
    transfer_inline_write(struct pipe_resource *resource,
-                         struct pipe_subresource *sr,
+                         unsigned level,
                          unsigned usage,
                          const struct pipe_box *box,
                          const char *STRING, unsigned LENGTH,
                          unsigned stride,
-                         unsigned slice_stride)
+                         unsigned layer_stride)
    {
       struct pipe_context *pipe = $self->pipe;
 
-      pipe->transfer_inline_write(pipe, resource, *sr, usage, box, STRING, stride, slice_stride);
+      pipe->transfer_inline_write(pipe, resource, level, usage, box, STRING, stride, layer_stride);
    }
 
    %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
diff --git a/src/gallium/state_trackers/python/p_state.i b/src/gallium/state_trackers/python/p_state.i
index c1e6ea1..0537557 100644
--- a/src/gallium/state_trackers/python/p_state.i
+++ b/src/gallium/state_trackers/python/p_state.i
@@ -114,7 +114,8 @@
          SWIG_exception(SWIG_ValueError, "index out of bounds");
       
       if(surface) {
-         _surface = st_pipe_surface(surface, PIPE_BIND_RENDER_TARGET);
+         /* XXX need a context here */
+         _surface = st_pipe_surface(NULL, surface, PIPE_BIND_RENDER_TARGET);
          if(!_surface)
             SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing");
       }
@@ -131,7 +132,8 @@
       struct pipe_surface *_surface = NULL;
 
       if(surface) {
-         _surface = st_pipe_surface(surface, PIPE_BIND_DEPTH_STENCIL);
+         /* XXX need a context here */
+         _surface = st_pipe_surface(NULL, surface, PIPE_BIND_DEPTH_STENCIL);
          if(!_surface)
             SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing");
       }
diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i
index ae50694..1f4b4fd 100644
--- a/src/gallium/state_trackers/python/p_texture.i
+++ b/src/gallium/state_trackers/python/p_texture.i
@@ -42,9 +42,8 @@
 %ignore pipe_resource::screen;
 
 %immutable st_surface::texture;
-%immutable st_surface::face;
 %immutable st_surface::level;
-%immutable st_surface::zslice;
+%immutable st_surface::layer;
 
 %newobject pipe_resource::get_surface;
 
@@ -73,25 +72,23 @@
 
    /** Get a surface which is a "view" into a texture */
    struct st_surface *
-   get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0)
+   get_surface(unsigned level=0, unsigned layer=0)
    {
       struct st_surface *surface;
 
-      if(face >= ($self->target == PIPE_TEXTURE_CUBE ? 6U : 1U))
-         SWIG_exception(SWIG_ValueError, "face out of bounds");
       if(level > $self->last_level)
          SWIG_exception(SWIG_ValueError, "level out of bounds");
-      if(zslice >= u_minify($self->depth0, level))
-         SWIG_exception(SWIG_ValueError, "zslice out of bounds");
+      if(layer >= ($self->target == PIPE_TEXTURE_3D ?
+                         u_minify($self->depth0, level) : $self->depth0))
+         SWIG_exception(SWIG_ValueError, "layer out of bounds");
 
       surface = CALLOC_STRUCT(st_surface);
       if(!surface)
          return NULL;
 
       pipe_resource_reference(&surface->texture, $self);
-      surface->face = face;
       surface->level = level;
-      surface->zslice = zslice;
+      surface->layer = layer;
 
       return surface;
 
@@ -113,9 +110,8 @@
    %immutable;
 
    struct pipe_resource *texture;
-   unsigned face;
    unsigned level;
-   unsigned zslice;
+   unsigned layer;
 
 };
 
diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c
index 2981345..d0a4295 100644
--- a/src/gallium/state_trackers/python/st_device.c
+++ b/src/gallium/state_trackers/python/st_device.c
@@ -240,6 +240,7 @@
       templat.width0 = 1;
       templat.height0 = 1;
       templat.depth0 = 1;
+      templat.array_size = 1;
       templat.last_level = 0;
       templat.bind = PIPE_BIND_SAMPLER_VIEW;
    
@@ -252,7 +253,7 @@
 
 	 pipe->transfer_inline_write(pipe,
 				     st_ctx->default_texture,
-				     u_subresource(0,0),
+				     0,
 				     PIPE_TRANSFER_WRITE,
 				     &box,
 				     &zero,
diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h
index 2dca7a1..53e2556 100644
--- a/src/gallium/state_trackers/python/st_device.h
+++ b/src/gallium/state_trackers/python/st_device.h
@@ -41,9 +41,8 @@
 struct st_surface
 {
    struct pipe_resource *texture;
-   unsigned face;
    unsigned level;
-   unsigned zslice;
+   unsigned layer;
 };
 
 
@@ -83,11 +82,17 @@
 
 
 static INLINE struct pipe_surface *
-st_pipe_surface(struct st_surface *surface, unsigned usage) 
+st_pipe_surface(struct pipe_context *pipe, struct st_surface *surface, unsigned usage) 
 {
    struct pipe_resource *texture = surface->texture;
-   struct pipe_screen *screen = texture->screen;
-   return screen->get_tex_surface(screen, texture, surface->face, surface->level, surface->zslice, usage);
+   struct pipe_surface surf_tmpl;
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   surf_tmpl.format = texture->format;
+   surf_tmpl.usage = usage;
+   surf_tmpl.u.tex.level = surface->level;
+   surf_tmpl.u.tex.first_layer = surface->layer;
+   surf_tmpl.u.tex.last_layer = surface->layer;
+   return pipe->create_surface(pipe, texture, &surf_tmpl);
 }
 
 struct st_context *
diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c
index 25bfbf1..cac9a1a 100644
--- a/src/gallium/state_trackers/python/st_sample.c
+++ b/src/gallium/state_trackers/python/st_sample.c
@@ -555,9 +555,8 @@
 
    transfer = pipe_get_transfer(pipe,
                                 surface->texture,
-                                surface->face,
                                 surface->level,
-                                surface->zslice,
+                                surface->layer,
                                 PIPE_TRANSFER_WRITE,
                                 0, 0,
                                 width,
diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c
index 384554a..95f900f 100644
--- a/src/gallium/state_trackers/vega/api_filters.c
+++ b/src/gallium/state_trackers/vega/api_filters.c
@@ -41,7 +41,6 @@
 #include "util/u_sampler.h"
 #include "util/u_string.h"
 
-
 #include "asm_filters.h"
 
 
@@ -72,6 +71,7 @@
    templ.width0 = color_data_len;
    templ.height0 = 1;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.bind = PIPE_BIND_SAMPLER_VIEW;
 
    tex = screen->resource_create(screen, &templ);
@@ -79,9 +79,9 @@
    { /* upload color_data */
       struct pipe_transfer *transfer =
          pipe_get_transfer(pipe, tex,
-				0, 0, 0,
-				PIPE_TRANSFER_READ_WRITE ,
-				0, 0, tex->width0, tex->height0);
+                           0, 0,
+                           PIPE_TRANSFER_READ_WRITE ,
+                           0, 0, tex->width0, tex->height0);
       void *map = pipe->transfer_map(pipe, transfer);
       memcpy(map, color_data, sizeof(VGint)*color_data_len);
       pipe->transfer_unmap(pipe, transfer);
diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c
index 60f9db6..ad95409 100644
--- a/src/gallium/state_trackers/vega/api_images.c
+++ b/src/gallium/state_trackers/vega/api_images.c
@@ -447,9 +447,9 @@
       VGint y = (stfb->height - sy) - 1, yStep = -1;
       struct pipe_transfer *transfer;
 
-      transfer = pipe_get_transfer(pipe, strb->texture,  0, 0, 0,
-				   PIPE_TRANSFER_READ,
-				   0, 0, sx + width, stfb->height - sy);
+      transfer = pipe_get_transfer(pipe, strb->texture,  0, 0,
+                                   PIPE_TRANSFER_READ,
+                                   0, 0, sx + width, stfb->height - sy);
 
       /* Do a row at a time to flip image data vertically */
       for (i = 0; i < height; i++) {
diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c
index a20b6d5..164af30 100644
--- a/src/gallium/state_trackers/vega/image.c
+++ b/src/gallium/state_trackers/vega/image.c
@@ -42,6 +42,7 @@
 #include "util/u_memory.h"
 #include "util/u_math.h"
 #include "util/u_sampler.h"
+#include "util/u_surface.h"
 
 static enum pipe_format vg_format_to_pipe(VGImageFormat format)
 {
@@ -135,11 +136,11 @@
 
    if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
        dst_loc[2] >= 0 && dst_loc[3] >= 0) {
-      struct pipe_surface *surf;
+      struct pipe_surface *surf, surf_tmpl;
 
       /* get the destination surface */
-      surf = ctx->pipe->screen->get_tex_surface(ctx->pipe->screen,
-            dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+      u_surface_default_template(&surf_tmpl, dst, PIPE_BIND_RENDER_TARGET);
+      surf = ctx->pipe->create_surface(ctx->pipe, dst, &surf_tmpl);
       if (surf && renderer_copy_begin(ctx->renderer, surf, VG_TRUE, src)) {
          renderer_copy(ctx->renderer,
                dst_loc[0], dst_loc[1], dst_loc[2], dst_loc[3],
@@ -265,6 +266,7 @@
    pt.width0 = width;
    pt.height0 = height;
    pt.depth0 = 1;
+   pt.array_size = 1;
    pt.bind = PIPE_BIND_SAMPLER_VIEW;
 
    newtex = screen->resource_create(screen, &pt);
@@ -415,7 +417,7 @@
 
    { /* upload color_data */
       struct pipe_transfer *transfer = pipe_get_transfer(
-         pipe, texture, 0, 0, 0,
+         pipe, texture, 0, 0,
          PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0);
       src += (dataStride * yoffset);
       for (i = 0; i < height; i++) {
@@ -446,11 +448,11 @@
    {
       struct pipe_transfer *transfer =
          pipe_get_transfer(pipe,
-                                  image->sampler_view->texture,  0, 0, 0,
-                                  PIPE_TRANSFER_READ,
-                                  0, 0,
-                                  image->x + image->width,
-                                  image->y + image->height);
+                           image->sampler_view->texture,  0, 0,
+                           PIPE_TRANSFER_READ,
+                           0, 0,
+                           image->x + image->width,
+                           image->y + image->height);
       /* Do a row at a time to flip image data vertically */
       for (i = 0; i < height; i++) {
 #if 0
@@ -566,20 +568,21 @@
 {
    struct vg_context *ctx = vg_current_context();
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   struct pipe_surface *surf;
+   struct pipe_surface *surf, surf_tmpl;
    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
 
    /* make sure rendering has completed */
    pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
 
-   surf = screen->get_tex_surface(screen, image_texture(src),  0, 0, 0,
-                                  0 /* no bind flags as surf isn't actually used??? */);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, image_texture(src),
+                              0 /* no bind flag - not a surface*/);
+   surf = pipe->create_surface(pipe, image_texture(src), &surf_tmpl);
 
    vg_copy_surface(ctx, strb->surface, dx, dy,
                    surf, sx+src->x, sy+src->y, width, height);
 
-   screen->tex_surface_destroy(surf);
+   pipe->surface_destroy(pipe, surf);
 }
 
 void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
@@ -588,8 +591,7 @@
 {
    struct vg_context *ctx = vg_current_context();
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   struct pipe_surface *surf;
+   struct pipe_surface *surf, surf_tmpl;
    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
 
    /* flip the y coordinates */
@@ -598,8 +600,10 @@
    /* make sure rendering has completed */
    pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
 
-   surf = screen->get_tex_surface(screen, image_texture(dst),  0, 0, 0,
-                                  0 /* no bind flags as surf isn't actually used??? */);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, image_texture(dst),
+                              PIPE_BIND_RENDER_TARGET);
+   surf = pipe->create_surface(pipe, image_texture(dst), &surf_tmpl);
 
    vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
                    strb->surface, sx, sy, width, height);
diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c
index 8431e1b..d8dc85f 100644
--- a/src/gallium/state_trackers/vega/mask.c
+++ b/src/gallium/state_trackers/vega/mask.c
@@ -37,6 +37,7 @@
 #include "util/u_inlines.h"
 #include "util/u_format.h"
 #include "util/u_memory.h"
+#include "util/u_surface.h"
 #include "util/u_sampler.h"
 
 struct vg_mask_layer {
@@ -99,7 +100,6 @@
 {
    struct vg_context *ctx = vg_current_context();
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
 
    struct st_framebuffer *stfb = ctx->draw_buffer;
    struct st_renderbuffer *strb = stfb->alpha_mask;
@@ -130,8 +130,8 @@
    {
       struct pipe_surface *surf;
 
-      surf = screen->get_tex_surface(screen, strb->texture,  0, 0, 0,
-                                     PIPE_BIND_TRANSFER_READ);
+      surf = pipe->create_surface(pipe, strb->texture,  0, 0, 0,
+                                  PIPE_BIND_TRANSFER_READ);
 
       /* Do a row at a time to flip image data vertically */
       for (i = 0; i < height; i++) {
@@ -400,11 +400,13 @@
 {
    struct vg_context *ctx = vg_current_context();
    struct pipe_sampler_view *src = vg_get_surface_mask(ctx);
-   struct pipe_surface *surf;
+   struct pipe_surface *surf, surf_tmpl;
 
    /* get the destination surface */
-   surf = ctx->pipe->screen->get_tex_surface(ctx->pipe->screen,
-         layer->sampler_view->texture, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+   u_surface_default_template(&surf_tmpl, layer->sampler_view->texture,
+                              PIPE_BIND_RENDER_TARGET);
+   surf = ctx->pipe->create_surface(ctx->pipe, layer->sampler_view->texture,
+                                    &surf_tmpl);
    if (surf && renderer_copy_begin(ctx->renderer, surf, VG_FALSE, src)) {
       /* layer should be flipped when used as a texture */
       sy += height;
@@ -424,13 +426,13 @@
                                  VGbitfield paint_modes)
 {
    struct vg_context *ctx = vg_current_context();
-   struct pipe_screen *screen = ctx->pipe->screen;
+   struct pipe_context *pipe = ctx->pipe;
    struct pipe_sampler_view *view = vg_get_surface_mask(ctx);
    struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
-   struct pipe_surface *surf;
-
-   surf = screen->get_tex_surface(screen, view->texture,
-                                  0, 0, 0, PIPE_BIND_RENDER_TARGET);
+   struct pipe_surface *surf, surf_tmpl;
+   u_surface_default_template(&surf_tmpl, view->texture,
+                              PIPE_BIND_RENDER_TARGET);
+   surf = pipe->create_surface(pipe, view->texture, &surf_tmpl);
 
    renderer_validate_for_mask_rendering(ctx->renderer, surf);
 
diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c
index 31c1784..2db8cbc 100644
--- a/src/gallium/state_trackers/vega/paint.c
+++ b/src/gallium/state_trackers/vega/paint.c
@@ -154,14 +154,15 @@
    templ.width0 = 1024;
    templ.height0 = 1;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.bind = PIPE_BIND_SAMPLER_VIEW;
 
    tex = screen->resource_create(screen, &templ);
 
    { /* upload color_data */
       struct pipe_transfer *transfer =
-         pipe_get_transfer(p->base.ctx->pipe, tex, 0, 0, 0,
-                                      PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
+         pipe_get_transfer(p->base.ctx->pipe, tex, 0, 0,
+                           PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
       void *map = pipe->transfer_map(pipe, transfer);
       memcpy(map, p->gradient.color_data, sizeof(VGint)*1024);
       pipe->transfer_unmap(pipe, transfer);
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c
index 169526b..080bcf6 100644
--- a/src/gallium/state_trackers/vega/renderer.c
+++ b/src/gallium/state_trackers/vega/renderer.c
@@ -40,6 +40,7 @@
 #include "util/u_simple_shaders.h"
 #include "util/u_memory.h"
 #include "util/u_sampler.h"
+#include "util/u_surface.h"
 #include "util/u_math.h"
 
 #include "cso_cache/cso_context.h"
@@ -815,7 +816,7 @@
                                 const void *const_buffer,
                                 VGint const_buffer_len)
 {
-   struct pipe_surface *surf;
+   struct pipe_surface *surf, surf_tmpl;
 
    assert(renderer->state == RENDERER_STATE_INIT);
 
@@ -824,8 +825,9 @@
    if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
       return VG_FALSE;
 
-   surf = renderer->pipe->screen->get_tex_surface(renderer->pipe->screen,
-         dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+   u_surface_default_template(&surf_tmpl, dst,
+                              PIPE_BIND_RENDER_TARGET);
+   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
    if (!surf)
       return VG_FALSE;
 
@@ -1380,8 +1382,8 @@
    struct pipe_screen *screen = pipe->screen;
    struct pipe_sampler_view view_templ;
    struct pipe_sampler_view *view;
+   struct pipe_box src_box;
    struct pipe_resource texTemp, *tex;
-   struct pipe_subresource subsrc, subdst;
    const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
    const int srcW = abs(srcX1 - srcX0);
    const int srcH = abs(srcY1 - srcY0);
@@ -1425,6 +1427,7 @@
    texTemp.width0 = srcW;
    texTemp.height0 = srcH;
    texTemp.depth0 = 1;
+   texTemp.array_size = 1;
    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
    tex = screen->resource_create(screen, &texTemp);
@@ -1437,15 +1440,11 @@
    if (!view)
       return;
 
-   subdst.face = 0;
-   subdst.level = 0;
-   subsrc.face = src->face;
-   subsrc.level = src->level;
+   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
 
    pipe->resource_copy_region(pipe,
-                              tex, subdst, 0, 0, 0,  /* dest */
-                              src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */
-                              srcW, srcH);     /* size */
+                              tex, 0, 0, 0, 0,  /* dest */
+                              src->texture, 0, &src_box);
 
    assert(floatsEqual(z, 0.0f));
 
diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c
index 5b07265..5479edc 100644
--- a/src/gallium/state_trackers/vega/vg_context.c
+++ b/src/gallium/state_trackers/vega/vg_context.c
@@ -44,6 +44,7 @@
 #include "util/u_memory.h"
 #include "util/u_blit.h"
 #include "util/u_sampler.h"
+#include "util/u_surface.h"
 #include "util/u_format.h"
 
 struct vg_context *_vg_context = 0;
@@ -241,6 +242,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
 
    if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
@@ -310,22 +312,18 @@
 
    /* if we had an old surface copy it over */
    if (old_sampler_view) {
-      struct pipe_subresource subsurf, subold_surf;
-      subsurf.face = 0;
-      subsurf.level = 0;
-      subold_surf.face = 0;
-      subold_surf.level = 0;
+      struct pipe_box src_box;
+      u_box_origin_2d(MIN2(old_sampler_view->texture->width0,
+                           stfb->surface_mask_view->texture->width0),
+                      MIN2(old_sampler_view->texture->height0,
+                           stfb->surface_mask_view->texture->height0),
+                      &src_box);
+
       pipe->resource_copy_region(pipe,
                                  stfb->surface_mask_view->texture,
-                                 subsurf,
-                                 0, 0, 0,
+                                 0, 0, 0, 0,
                                  old_sampler_view->texture,
-                                 subold_surf,
-                                 0, 0, 0,
-                                 MIN2(old_sampler_view->texture->width0,
-                                      stfb->surface_mask_view->texture->width0),
-                                 MIN2(old_sampler_view->texture->height0,
-                                      stfb->surface_mask_view->texture->height0));
+                                 0, &src_box);
    }
 
    /* Free the old texture
@@ -359,7 +357,7 @@
 {
    struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
    struct pipe_context *pipe = ctx->pipe;
-   unsigned surface_usage;
+   struct pipe_surface surf_tmpl;
 
    if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
       return FALSE;
@@ -369,18 +367,16 @@
    pipe_resource_reference(&dsrb->texture, NULL);
    dsrb->width = dsrb->height = 0;
 
-   /* Probably need dedicated flags for surface usage too:
-    */
-   surface_usage = PIPE_BIND_DEPTH_STENCIL; /* XXX: was: RENDER_TARGET */
-
    dsrb->texture = create_texture(pipe, dsrb->format, width, height);
    if (!dsrb->texture)
       return TRUE;
 
-   dsrb->surface = pipe->screen->get_tex_surface(pipe->screen,
-                                                 dsrb->texture,
-                                                 0, 0, 0,
-                                                 surface_usage);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, dsrb->texture,
+                              PIPE_BIND_DEPTH_STENCIL);
+   dsrb->surface = pipe->create_surface(pipe,
+                                        dsrb->texture,
+                                        &surf_tmpl);
    if (!dsrb->surface) {
       pipe_resource_reference(&dsrb->texture, NULL);
       return TRUE;
@@ -439,11 +435,16 @@
 {
    struct st_framebuffer *stfb = ctx->draw_buffer;
    struct pipe_surface *surf;
+   struct pipe_surface surf_tmpl;
 
    vg_context_update_blend_texture_view(ctx, stfb->width, stfb->height);
 
-   surf = ctx->pipe->screen->get_tex_surface(ctx->pipe->screen,
-         stfb->blend_texture_view->texture, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, stfb->blend_texture_view->texture,
+                              PIPE_BIND_RENDER_TARGET);
+   surf = ctx->pipe->create_surface(ctx->pipe,
+                                    stfb->blend_texture_view->texture,
+                                    &surf_tmpl);
    if (surf) {
       util_blit_pixels_tex(ctx->blit,
                            src, 0, 0, stfb->width, stfb->height,
diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c
index 03c8d22..d538e66 100644
--- a/src/gallium/state_trackers/vega/vg_manager.c
+++ b/src/gallium/state_trackers/vega/vg_manager.c
@@ -34,6 +34,8 @@
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
 #include "util/u_sampler.h"
+#include "util/u_box.h"
+#include "util/u_surface.h"
 
 #include "vg_api.h"
 #include "vg_manager.h"
@@ -45,7 +47,8 @@
 vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
 {
    struct st_renderbuffer *strb = ctx->draw_buffer->strb;
-   struct pipe_screen *screen = ctx->pipe->screen;
+   struct pipe_context *pipe = ctx->pipe;
+   struct pipe_surface surf_tmpl;
 
    if (strb->texture == pt) {
       pipe_resource_reference(&pt, NULL);
@@ -58,8 +61,12 @@
    strb->width = strb->height = 0;
 
    strb->texture = pt;
-   strb->surface = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
-                                           PIPE_BIND_RENDER_TARGET);
+
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, strb->texture,
+                              PIPE_BIND_RENDER_TARGET);
+   strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl);
+
    if (!strb->surface) {
       pipe_resource_reference(&strb->texture, NULL);
       return TRUE;
diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c
index 259b22f..733222a 100644
--- a/src/gallium/state_trackers/wgl/stw_framebuffer.c
+++ b/src/gallium/state_trackers/wgl/stw_framebuffer.c
@@ -469,7 +469,7 @@
 {
    struct stw_framebuffer *fb;
    struct pipe_screen *screen;
-   struct pipe_surface *surface;
+   struct pipe_resource *res;
 
    if (!stw_dev)
       return FALSE;
@@ -480,7 +480,7 @@
 
    screen = stw_dev->screen;
 
-   surface = (struct pipe_surface *)data->pPrivateData;
+   res = (struct pipe_resource *)data->pPrivateData;
 
    if(data->hSharedSurface != fb->hSharedSurface) {
       if(fb->shared_surface) {
@@ -498,13 +498,13 @@
 
    if(fb->shared_surface) {
       stw_dev->stw_winsys->compose(screen,
-                                   surface,
+                                   res,
                                    fb->shared_surface,
                                    &fb->client_rect,
                                    data->PresentHistoryToken);
    }
    else {
-      stw_dev->stw_winsys->present( screen, surface, hdc );
+      stw_dev->stw_winsys->present( screen, res, hdc );
    }
 
    stw_framebuffer_update(fb);
@@ -524,7 +524,7 @@
 BOOL
 stw_framebuffer_present_locked(HDC hdc,
                                struct stw_framebuffer *fb,
-                               struct pipe_surface *surface)
+                               struct pipe_resource *res)
 {
    if(stw_dev->callbacks.wglCbPresentBuffers &&
       stw_dev->stw_winsys->compose) {
@@ -535,7 +535,7 @@
       data.magic2 = 0;
       data.AdapterLuid = stw_dev->AdapterLuid;
       data.rect = fb->client_rect;
-      data.pPrivateData = (void *)surface;
+      data.pPrivateData = (void *)res;
 
       stw_notify_current_locked(fb);
       stw_framebuffer_release(fb);
@@ -545,7 +545,7 @@
    else {
       struct pipe_screen *screen = stw_dev->screen;
 
-      stw_dev->stw_winsys->present( screen, surface, hdc );
+      stw_dev->stw_winsys->present( screen, res, hdc );
 
       stw_framebuffer_update(fb);
       stw_notify_current_locked(fb);
diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.h b/src/gallium/state_trackers/wgl/stw_framebuffer.h
index 89d1230..6604e54 100644
--- a/src/gallium/state_trackers/wgl/stw_framebuffer.h
+++ b/src/gallium/state_trackers/wgl/stw_framebuffer.h
@@ -32,7 +32,7 @@
 
 #include "os/os_thread.h"
 
-struct pipe_surface;
+struct pipe_resource;
 struct st_framebuffer_iface;
 struct stw_pixelformat_info;
 
@@ -143,7 +143,7 @@
 BOOL
 stw_framebuffer_present_locked(HDC hdc,
                                struct stw_framebuffer *fb,
-                               struct pipe_surface *surface);
+                               struct pipe_resource *res);
 
 void
 stw_framebuffer_update(
diff --git a/src/gallium/state_trackers/wgl/stw_st.c b/src/gallium/state_trackers/wgl/stw_st.c
index bcdd82e..40ea2f4 100644
--- a/src/gallium/state_trackers/wgl/stw_st.c
+++ b/src/gallium/state_trackers/wgl/stw_st.c
@@ -44,7 +44,7 @@
    unsigned texture_width, texture_height;
    unsigned texture_mask;
 
-   struct pipe_surface *front_surface, *back_surface;
+   struct pipe_resource *front_res, *back_res;
 };
 
 static INLINE struct stw_st_framebuffer *
@@ -66,8 +66,8 @@
    unsigned i;
 
    /* remove outdated surface */
-   pipe_surface_reference(&stwfb->front_surface, NULL);
-   pipe_surface_reference(&stwfb->back_surface, NULL);
+   pipe_resource_reference(&stwfb->front_res, NULL);
+   pipe_resource_reference(&stwfb->back_res, NULL);
 
    /* remove outdated textures */
    if (stwfb->texture_width != width || stwfb->texture_height != height) {
@@ -80,6 +80,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
@@ -155,19 +156,22 @@
    return TRUE;
 }
 
-static struct pipe_surface *
+static struct pipe_resource *
 get_present_surface_locked(struct st_framebuffer_iface *stfb,
                            enum st_attachment_type statt)
 {
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
+#if 0
+   /* since we don't really have to get a surface for this we
+      no longer need a cache? */
    struct pipe_resource *ptex;
-   struct pipe_surface *psurf, **cache;
-   
+   struct pipe_resource *pres, **cache;
+
    ptex = stwfb->textures[statt];
    if (!ptex)
       return NULL;
 
-   psurf = NULL;
+   pres = NULL;
 
    switch (statt) {
    case ST_ATTACHMENT_FRONT_LEFT:
@@ -177,21 +181,21 @@
       cache = &stwfb->back_surface;
       break;
    default:
-      cache = &psurf;
+      cache = &pres;
       break;
    }
 
    if (!*cache) {
-      *cache = stw_dev->screen->get_tex_surface(stw_dev->screen,
-            ptex, 0, 0, 0,
-            PIPE_BIND_DISPLAY_TARGET |
-            PIPE_BIND_RENDER_TARGET);
+      *cache = ptex;
    }
 
-   if (psurf != *cache)
-      pipe_surface_reference(&psurf, *cache);
+   if (pres != *cache)
+      pipe_resource_reference(&pres, *cache);
 
-   return psurf;
+   return pres;
+#else
+   return stwfb->textures[statt];
+#endif
 }
 
 /**
@@ -202,12 +206,12 @@
                                   enum st_attachment_type statt)
 {
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
-   struct pipe_surface *psurf;
-   
-   psurf = get_present_surface_locked(&stwfb->base, statt);
-   if (psurf) {
-      stw_framebuffer_present_locked(stwfb->fb->hDC, stwfb->fb, psurf);
-      pipe_surface_reference(&psurf, NULL);
+   struct pipe_resource *pres;
+
+   pres = get_present_surface_locked(&stwfb->base, statt);
+   if (pres) {
+      stw_framebuffer_present_locked(stwfb->fb->hDC, stwfb->fb, pres);
+      pipe_resource_reference(&pres, NULL);
    }
 
    return TRUE;
@@ -255,8 +259,8 @@
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
    int i;
 
-   pipe_surface_reference(&stwfb->front_surface, NULL);
-   pipe_surface_reference(&stwfb->back_surface, NULL);
+   pipe_resource_reference(&stwfb->front_res, NULL);
+   pipe_resource_reference(&stwfb->back_res, NULL);
 
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
       pipe_resource_reference(&stwfb->textures[i], NULL);
@@ -273,7 +277,7 @@
    struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb);
    unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT;
    struct pipe_resource *ptex;
-   struct pipe_surface *psurf;
+   struct pipe_resource *pres;
    unsigned mask;
 
    /* swap the textures */
@@ -282,9 +286,9 @@
    stwfb->textures[back] = ptex;
 
    /* swap the surfaces */
-   psurf = stwfb->front_surface;
-   stwfb->front_surface = stwfb->back_surface;
-   stwfb->back_surface = psurf;
+   pres = stwfb->front_res;
+   stwfb->front_res = stwfb->back_res;
+   stwfb->back_res = pres;
 
    /* convert to mask */
    front = 1 << front;
diff --git a/src/gallium/state_trackers/wgl/stw_winsys.h b/src/gallium/state_trackers/wgl/stw_winsys.h
index 270fad5..397065f 100644
--- a/src/gallium/state_trackers/wgl/stw_winsys.h
+++ b/src/gallium/state_trackers/wgl/stw_winsys.h
@@ -34,7 +34,7 @@
 
 struct pipe_screen;
 struct pipe_context;
-struct pipe_surface;
+struct pipe_resource;
 
 struct stw_shared_surface;
 
@@ -43,12 +43,13 @@
    struct pipe_screen *
    (*create_screen)( void );
 
+   /* XXX is it actually possible to have non-zero level/layer ??? */
    /**
     * Present the color buffer to the window associated with the device context.
     */
    void
    (*present)( struct pipe_screen *screen,
-               struct pipe_surface *surf,
+               struct pipe_resource *res,
                HDC hDC );
 
    /**
@@ -85,7 +86,7 @@
     */
    void
    (*compose)( struct pipe_screen *screen,
-               struct pipe_surface *src,
+               struct pipe_resource *res,
                struct stw_shared_surface *dest,
                LPCRECT pRect,
                ULONGLONG PresentHistoryToken );
diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c
index 4ff4802..d4dc84a 100644
--- a/src/gallium/state_trackers/xorg/xorg_composite.c
+++ b/src/gallium/state_trackers/xorg/xorg_composite.c
@@ -473,7 +473,7 @@
                                   struct exa_pixmap_priv *pMask,
                                   struct exa_pixmap_priv *pDst)
 {
-   struct pipe_surface *dst_surf = xorg_gpu_surface(exa->scrn, pDst);
+   struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pDst);
 
    renderer_bind_destination(exa->renderer, dst_surf,
                              pDst->width,
@@ -529,7 +529,7 @@
                               struct exa_pixmap_priv *pixmap,
                               Pixel fg)
 {
-   struct pipe_surface *dst_surf = xorg_gpu_surface(exa->scrn, pixmap);
+   struct pipe_surface *dst_surf = xorg_gpu_surface(exa->pipe, pixmap);
    unsigned vs_traits, fs_traits;
    struct xorg_shader shader;
 
diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c
index 80af82d..28e30e0 100644
--- a/src/gallium/state_trackers/xorg/xorg_crtc.c
+++ b/src/gallium/state_trackers/xorg/xorg_crtc.c
@@ -210,6 +210,7 @@
 	templat.target = PIPE_TEXTURE_2D;
 	templat.last_level = 0;
 	templat.depth0 = 1;
+	templat.array_size = 1;
 	templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
 	templat.width0 = 64;
 	templat.height0 = 64;
@@ -225,9 +226,9 @@
     }
 
     transfer = pipe_get_transfer(ms->ctx, crtcp->cursor_tex,
-                                         0, 0, 0,
-                                         PIPE_TRANSFER_WRITE,
-                                         0, 0, 64, 64);
+                                 0, 0,
+                                 PIPE_TRANSFER_WRITE,
+                                 0, 0, 64, 64);
     ptr = ms->ctx->transfer_map(ms->ctx, transfer);
     util_copy_rect(ptr, crtcp->cursor_tex->format,
 		   transfer->stride, 0, 0,
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c
index b723a8e..17c34b7 100644
--- a/src/gallium/state_trackers/xorg/xorg_dri2.c
+++ b/src/gallium/state_trackers/xorg/xorg_dri2.c
@@ -129,6 +129,7 @@
 	    template.width0 = pDraw->width;
 	    template.height0 = pDraw->height;
 	    template.depth0 = 1;
+	    template.array_size = 1;
 	    template.last_level = 0;
 	    template.bind = PIPE_BIND_DEPTH_STENCIL |
 		PIPE_BIND_SHARED;
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index 4b1c02b..718a345 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -46,6 +46,8 @@
 #include "util/u_math.h"
 #include "util/u_debug.h"
 #include "util/u_format.h"
+#include "util/u_box.h"
+#include "util/u_surface.h"
 
 #define DEBUG_PRINT 0
 #define ROUND_UP_TEXTURES 1
@@ -188,8 +190,8 @@
     if (!priv || !priv->tex)
 	return FALSE;
 
-    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0,
-					   PIPE_TRANSFER_READ, x, y, w, h);
+    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
+                                 PIPE_TRANSFER_READ, x, y, w, h);
     if (!transfer)
 	return FALSE;
 
@@ -222,8 +224,8 @@
     if (!priv || !priv->tex)
 	return FALSE;
 
-    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0,
-					   PIPE_TRANSFER_WRITE, x, y, w, h);
+    transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
+                                 PIPE_TRANSFER_WRITE, x, y, w, h);
     if (!transfer)
 	return FALSE;
 
@@ -265,7 +267,7 @@
         assert(pPix->drawable.height <= priv->tex->height0);
 
 	priv->map_transfer =
-	   pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0,
+	   pipe_get_transfer(exa->pipe, priv->tex, 0, 0,
 #ifdef EXA_MIXED_PIXMAPS
 					PIPE_TRANSFER_MAP_DIRECTLY |
 #endif
@@ -449,6 +451,7 @@
        exa->copy.use_surface_copy = TRUE;
     }
     else {
+       struct pipe_surface surf_tmpl;
        exa->copy.use_surface_copy = FALSE;
 
        if (exa->copy.dst == exa->copy.src)
@@ -458,11 +461,13 @@
           pipe_resource_reference(&exa->copy.src_texture,
                                  exa->copy.src->tex);
 
+       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+       u_surface_default_template(&surf_tmpl, exa->copy.dst->tex,
+                                  PIPE_BIND_RENDER_TARGET);
        exa->copy.dst_surface =
-          exa->scrn->get_tex_surface(exa->scrn,
-                                     exa->copy.dst->tex,
-                                     0, 0, 0,
-                                     PIPE_BIND_RENDER_TARGET);
+          exa->pipe->create_surface(exa->pipe,
+                                    exa->copy.dst->tex,
+                                    &surf_tmpl);
 
 
        renderer_copy_prepare(exa->renderer, 
@@ -492,19 +497,14 @@
    (void) priv;
 
    if (exa->copy.use_surface_copy) {
-      struct pipe_subresource subdst, subsrc;
-      subdst.face = 0;
-      subdst.level = 0;
-      subsrc.face = 0;
-      subsrc.level = 0;
+      struct pipe_box src_box;
+      u_box_2d(srcX, srcY, width, height, &src_box);
       exa->pipe->resource_copy_region( exa->pipe,
                                        exa->copy.dst->tex,
-                                       subdst,
+                                       0,
                                        dstX, dstY, 0,
                                        exa->copy.src->tex,
-                                       subsrc,
-                                       srcX, srcY, 0,
-                                       width, height );
+                                       0, &src_box);
    }
    else {
       renderer_copy_pixmap(exa->renderer, 
@@ -874,24 +874,21 @@
         }
 
 	template.depth0 = 1;
+	template.array_size = 1;
 	template.last_level = 0;
 	template.bind = PIPE_BIND_RENDER_TARGET | priv->flags;
 	priv->tex_flags = priv->flags;
 	texture = exa->scrn->resource_create(exa->scrn, &template);
 
 	if (priv->tex) {
-	    struct pipe_subresource subdst, subsrc;
-
-	    subdst.face = 0;
-	    subdst.level = 0;
-	    subsrc.face = 0;
-	    subsrc.level = 0;
+            struct pipe_box src_box;
+            u_box_origin_2d(min(width, texture->width0),
+                            min(height, texture->height0),
+                            &src_box);
             exa->pipe->resource_copy_region(exa->pipe, texture,
-                                            subdst, 0, 0, 0,
+                                            0, 0, 0, 0,
                                             priv->tex,
-                                            subsrc, 0, 0, 0,
-                                            min(width, texture->width0),
-                                            min(height, texture->height0));
+                                            0, &src_box);
 	}
 
 	pipe_resource_reference(&priv->tex, texture);
@@ -947,6 +944,7 @@
     template.width0 = width;
     template.height0 = height;
     template.depth0 = 1;
+    template.array_size = 1;
     template.last_level = 0;
     template.bind |= PIPE_BIND_RENDER_TARGET;
     template.bind |= PIPE_BIND_SCANOUT;
@@ -1063,10 +1061,14 @@
 }
 
 struct pipe_surface *
-xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv)
+xorg_gpu_surface(struct pipe_context *pipe, struct exa_pixmap_priv *priv)
 {
-   return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0,
-                                PIPE_BIND_RENDER_TARGET);
+   struct pipe_surface surf_tmpl;
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   u_surface_default_template(&surf_tmpl, priv->tex,
+                              PIPE_BIND_RENDER_TARGET);
+
+   return pipe->create_surface(pipe, priv->tex, &surf_tmpl);
 
 }
 
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h
index 86a1afc..1f78f60 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.h
+++ b/src/gallium/state_trackers/xorg/xorg_exa.h
@@ -72,7 +72,7 @@
 } while(0)
 
 struct pipe_surface *
-xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv);
+xorg_gpu_surface(struct pipe_context *pipe, struct exa_pixmap_priv *priv);
 
 void xorg_exa_flush(struct exa_context *exa, uint pipeFlushFlags,
                     struct pipe_fence_handle **fence);
diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c
index 92f1cc5..a3d7c5a 100644
--- a/src/gallium/state_trackers/xorg/xorg_renderer.c
+++ b/src/gallium/state_trackers/xorg/xorg_renderer.c
@@ -10,6 +10,7 @@
 #include "util/u_sampler.h"
 
 #include "util/u_inlines.h"
+#include "util/u_box.h"
 
 #include <math.h>
 
@@ -535,6 +536,7 @@
    templ.width0 = src->width0;
    templ.height0 = src->height0;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.bind = PIPE_BIND_SAMPLER_VIEW;
 
    pt = screen->resource_create(screen, &templ);
@@ -546,19 +548,15 @@
 
    {
       /* copy source framebuffer surface into texture */
-      struct pipe_subresource subsrc, subdst;
-      subsrc.face = 0;
-      subsrc.level = 0;
-      subdst.face = 0;
-      subdst.level = 0;
+      struct pipe_box src_box;
+      u_box_origin_2d(src->width0, src->height0, &src_box);
+
       pipe->resource_copy_region(pipe,
                                  pt, /* dest */
-                                 subdst,
+                                 0, /* dest_level */
                                  0, 0, 0, /* destx/y/z */
                                  src,
-                                 subsrc,
-                                 0, 0, 0,
-                                 src->width0, src->height0);
+                                 0, &src_box);
    }
 
    return pt;
diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c
index f64959f..c72ba9e 100644
--- a/src/gallium/state_trackers/xorg/xorg_xv.c
+++ b/src/gallium/state_trackers/xorg/xorg_xv.c
@@ -171,6 +171,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.bind = PIPE_BIND_SAMPLER_VIEW;
 
    tex = screen->resource_create(screen, &templ);
@@ -312,17 +313,17 @@
    int y_array_size = w * h;
 
    ytrans = pipe_get_transfer(pipe, dst[0],
-                                   0, 0, 0,
-                                   PIPE_TRANSFER_WRITE,
-                                   left, top, w, h);
+                              0, 0,
+                              PIPE_TRANSFER_WRITE,
+                              left, top, w, h);
    utrans = pipe_get_transfer(pipe, dst[1],
-                                   0, 0, 0,
-                                   PIPE_TRANSFER_WRITE,
-                                   left, top, w, h);
+                              0, 0,
+                              PIPE_TRANSFER_WRITE,
+                              left, top, w, h);
    vtrans = pipe_get_transfer(pipe, dst[2],
-                                   0, 0, 0,
-                                   PIPE_TRANSFER_WRITE,
-                                   left, top, w, h);
+                              0, 0,
+                              PIPE_TRANSFER_WRITE,
+                              left, top, w, h);
 
    ymap = (char*)pipe->transfer_map(pipe, ytrans);
    umap = (char*)pipe->transfer_map(pipe, utrans);
@@ -533,7 +534,7 @@
    if (!dst || !dst->tex)
       XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
 
-   dst_surf = xorg_gpu_surface(pPriv->r->pipe->screen, dst);
+   dst_surf = xorg_gpu_surface(pPriv->r->pipe, dst);
    hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
 
 #ifdef COMPOSITE
diff --git a/src/gallium/targets/libgl-gdi/libgl_gdi.c b/src/gallium/targets/libgl-gdi/libgl_gdi.c
index 1d6e664..112904a 100644
--- a/src/gallium/targets/libgl-gdi/libgl_gdi.c
+++ b/src/gallium/targets/libgl-gdi/libgl_gdi.c
@@ -100,7 +100,7 @@
 
 static void
 gdi_present(struct pipe_screen *screen,
-            struct pipe_surface *surface,
+            struct pipe_resource *res,
             HDC hDC)
 {
    /* This will fail if any interposing layer (trace, debug, etc) has
@@ -119,14 +119,14 @@
 #ifdef HAVE_LLVMPIPE
    if (use_llvmpipe) {
       winsys = llvmpipe_screen(screen)->winsys;
-      dt = llvmpipe_resource(surface->texture)->dt;
+      dt = llvmpipe_resource(res)->dt;
       gdi_sw_display(winsys, dt, hDC);
       return;
    }
 #endif
 
    winsys = softpipe_screen(screen)->winsys,
-   dt = softpipe_resource(surface->texture)->dt,
+   dt = softpipe_resource(res)->dt,
    gdi_sw_display(winsys, dt, hDC);
 }
 
diff --git a/src/gallium/tests/graw/clear.c b/src/gallium/tests/graw/clear.c
index ee4581e..1ff80ca 100644
--- a/src/gallium/tests/graw/clear.c
+++ b/src/gallium/tests/graw/clear.c
@@ -20,6 +20,7 @@
 struct pipe_screen *screen;
 struct pipe_context *ctx;
 struct pipe_surface *surf;
+struct pipe_resource *tex;
 static void *window = NULL;
 
 static void draw( void )
@@ -31,13 +32,14 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window);
 }
 
 static void init( void )
 {
    struct pipe_framebuffer_state fb;
-   struct pipe_resource *tex, templat;
+   struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -66,6 +68,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -76,9 +79,12 @@
    if (tex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, tex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
index 19af83f..37be2d0 100644
--- a/src/gallium/tests/graw/fs-test.c
+++ b/src/gallium/tests/graw/fs-test.c
@@ -119,6 +119,7 @@
    templat.width0 = sizeof(constants1);
    templat.height0 = 1;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_CONSTANT_BUFFER;
@@ -139,7 +140,7 @@
 
       ctx->transfer_inline_write(ctx,
                                  constbuf1,
-                                 u_subresource(0,0),
+                                 0,
                                  PIPE_TRANSFER_WRITE,
                                  &box,
                                  constants1,
@@ -156,7 +157,7 @@
 
       ctx->transfer_inline_write(ctx,
                                  constbuf2,
-                                 u_subresource(0,0),
+                                 0,
                                  PIPE_TRANSFER_WRITE,
                                  &box,
                                  constants2,
@@ -280,7 +281,7 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
 }
 
 #define SIZE 16
@@ -340,6 +341,7 @@
    templat.width0 = SIZE;
    templat.height0 = SIZE;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_SAMPLER_VIEW;
@@ -354,7 +356,7 @@
 
    ctx->transfer_inline_write(ctx,
                               samptex,
-                              u_subresource(0,0),
+                              0,
                               PIPE_TRANSFER_WRITE,
                               &box,
                               tex2d,
@@ -368,7 +370,7 @@
       struct pipe_transfer *t;
       uint32_t *ptr;
       t = pipe_get_transfer(ctx, samptex,
-                            0, 0, 0, /* face, level, zslice */
+                            0, 0, /* level, layer */
                             PIPE_TRANSFER_READ,
                             0, 0, SIZE, SIZE); /* x, y, width, height */
 
@@ -387,8 +389,6 @@
    memset(&sv_template, 0, sizeof sv_template);
    sv_template.format = samptex->format;
    sv_template.texture = samptex;
-   sv_template.first_level = 0;
-   sv_template.last_level = 0;
    sv_template.swizzle_r = 0;
    sv_template.swizzle_g = 1;
    sv_template.swizzle_b = 2;
@@ -424,6 +424,7 @@
 {
    struct pipe_framebuffer_state fb;
    struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -450,6 +451,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -460,9 +462,12 @@
    if (rttex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c
index ef29f13..812666a 100644
--- a/src/gallium/tests/graw/gs-test.c
+++ b/src/gallium/tests/graw/gs-test.c
@@ -156,6 +156,7 @@
    templat.width0 = sizeof(constants1);
    templat.height0 = 1;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_CONSTANT_BUFFER;
@@ -172,7 +173,7 @@
 
       ctx->transfer_inline_write(ctx,
                                  constbuf1,
-                                 u_subresource(0,0),
+                                 0,
                                  PIPE_TRANSFER_WRITE,
                                  &box,
                                  constants1,
@@ -189,7 +190,7 @@
 
       ctx->transfer_inline_write(ctx,
                                  constbuf2,
-                                 u_subresource(0,0),
+                                 0,
                                  PIPE_TRANSFER_WRITE,
                                  &box,
                                  constants2,
@@ -344,7 +345,7 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
 }
 
 #define SIZE 16
@@ -404,6 +405,7 @@
    templat.width0 = SIZE;
    templat.height0 = SIZE;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_SAMPLER_VIEW;
@@ -418,7 +420,7 @@
 
    ctx->transfer_inline_write(ctx,
                               samptex,
-                              u_subresource(0,0),
+                              0,
                               PIPE_TRANSFER_WRITE,
                               &box,
                               tex2d,
@@ -432,7 +434,7 @@
       struct pipe_transfer *t;
       uint32_t *ptr;
       t = pipe_get_transfer(ctx, samptex,
-                            0, 0, 0, /* face, level, zslice */
+                            0, 0, /* level, layer */
                             PIPE_TRANSFER_READ,
                             0, 0, SIZE, SIZE); /* x, y, width, height */
 
@@ -451,8 +453,6 @@
    memset(&sv_template, 0, sizeof sv_template);
    sv_template.format = samptex->format;
    sv_template.texture = samptex;
-   sv_template.first_level = 0;
-   sv_template.last_level = 0;
    sv_template.swizzle_r = 0;
    sv_template.swizzle_g = 1;
    sv_template.swizzle_b = 2;
@@ -488,6 +488,7 @@
 {
    struct pipe_framebuffer_state fb;
    struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -514,6 +515,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -524,9 +526,12 @@
    if (rttex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c
index 35eade9..952131d 100644
--- a/src/gallium/tests/graw/quad-tex.c
+++ b/src/gallium/tests/graw/quad-tex.c
@@ -151,7 +151,7 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
 }
 
 #define SIZE 16
@@ -211,6 +211,7 @@
    templat.width0 = SIZE;
    templat.height0 = SIZE;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_SAMPLER_VIEW;
@@ -225,7 +226,7 @@
 
    ctx->transfer_inline_write(ctx,
                               samptex,
-                              u_subresource(0,0),
+                              0,
                               PIPE_TRANSFER_WRITE,
                               &box,
                               tex2d,
@@ -239,7 +240,7 @@
       struct pipe_transfer *t;
       uint32_t *ptr;
       t = pipe_get_transfer(ctx, samptex,
-                            0, 0, 0, /* face, level, zslice */
+                            0, 0, /* level, layer */
                             PIPE_TRANSFER_READ,
                             0, 0, SIZE, SIZE); /* x, y, width, height */
 
@@ -258,8 +259,6 @@
    memset(&sv_template, 0, sizeof sv_template);
    sv_template.format = samptex->format;
    sv_template.texture = samptex;
-   sv_template.first_level = 0;
-   sv_template.last_level = 0;
    sv_template.swizzle_r = 0;
    sv_template.swizzle_g = 1;
    sv_template.swizzle_b = 2;
@@ -295,6 +294,7 @@
 {
    struct pipe_framebuffer_state fb;
    struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -321,6 +321,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -331,9 +332,12 @@
    if (rttex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c
index 0a6c362..b53f0a0 100644
--- a/src/gallium/tests/graw/shader-leak.c
+++ b/src/gallium/tests/graw/shader-leak.c
@@ -28,6 +28,7 @@
 static struct pipe_screen *screen = NULL;
 static struct pipe_context *ctx = NULL;
 static struct pipe_surface *surf = NULL;
+static struct pipe_resource *tex = NULL;
 static void *window = NULL;
 
 struct vertex {
@@ -155,7 +156,7 @@
       ctx->delete_fs_state(ctx, fs);
    }
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window);
    ctx->destroy(ctx);
 
    exit(0);
@@ -165,7 +166,8 @@
 static void init( void )
 {
    struct pipe_framebuffer_state fb;
-   struct pipe_resource *tex, templat;
+   struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -203,11 +205,16 @@
       exit(4);
    }
 
-   surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
-   if (surf == NULL)
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, tex, &surf_tmpl);
+   if (surf == NULL) {
+      fprintf(stderr, "Unable to create tex surface!\n");
       exit(5);
+   }
 
    memset(&fb, 0, sizeof fb);
    fb.nr_cbufs = 1;
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
index 731c4e1..84ff3e6 100644
--- a/src/gallium/tests/graw/tri-gs.c
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -23,6 +23,7 @@
 static struct pipe_screen *screen = NULL;
 static struct pipe_context *ctx = NULL;
 static struct pipe_surface *surf = NULL;
+static struct pipe_resource *tex = NULL;
 static void *window = NULL;
 
 struct vertex {
@@ -164,14 +165,15 @@
    util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window);
 }
 
 
 static void init( void )
 {
    struct pipe_framebuffer_state fb;
-   struct pipe_resource *tex, templat;
+   struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -198,6 +200,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -208,9 +211,12 @@
    if (tex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, tex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
index 7644381..f33c061 100644
--- a/src/gallium/tests/graw/tri-instanced.c
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -27,6 +27,7 @@
 static struct pipe_screen *screen = NULL;
 static struct pipe_context *ctx = NULL;
 static struct pipe_surface *surf = NULL;
+static struct pipe_resource *tex = NULL;
 static void *window = NULL;
 
 struct vertex {
@@ -216,14 +217,15 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window);
 }
 
 
 static void init( void )
 {
    struct pipe_framebuffer_state fb;
-   struct pipe_resource *tex, templat;
+   struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -250,6 +252,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -260,9 +263,12 @@
    if (tex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, tex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c
index 025a147..2742c7c 100644
--- a/src/gallium/tests/graw/tri.c
+++ b/src/gallium/tests/graw/tri.c
@@ -25,6 +25,7 @@
 static struct pipe_screen *screen = NULL;
 static struct pipe_context *ctx = NULL;
 static struct pipe_surface *surf = NULL;
+static struct pipe_resource *tex = NULL;
 static void *window = NULL;
 
 struct vertex {
@@ -144,14 +145,15 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window);
 }
 
 
 static void init( void )
 {
    struct pipe_framebuffer_state fb;
-   struct pipe_resource *tex, templat;
+   struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -180,6 +182,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -192,11 +195,14 @@
       exit(4);
    }
 
-   surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, tex, &surf_tmpl);
    if (surf == NULL) {
-      fprintf(stderr, "Unable to get tex surface!\n");
+      fprintf(stderr, "Unable to create tex surface!\n");
       exit(5);
    }
 
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
index 440c40b..58908f3 100644
--- a/src/gallium/tests/graw/vs-test.c
+++ b/src/gallium/tests/graw/vs-test.c
@@ -87,6 +87,7 @@
    templat.width0 = sizeof(constants);
    templat.height0 = 1;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_CONSTANT_BUFFER;
@@ -101,7 +102,7 @@
 
    ctx->transfer_inline_write(ctx,
                               constbuf,
-                              u_subresource(0,0),
+                              0,
                               PIPE_TRANSFER_WRITE,
                               &box,
                               constants,
@@ -231,7 +232,7 @@
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, surf, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
 }
 
 #define SIZE 16
@@ -291,6 +292,7 @@
    templat.width0 = SIZE;
    templat.height0 = SIZE;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = PIPE_BIND_SAMPLER_VIEW;
@@ -305,7 +307,7 @@
 
    ctx->transfer_inline_write(ctx,
                               samptex,
-                              u_subresource(0,0),
+                              0,
                               PIPE_TRANSFER_WRITE,
                               &box,
                               tex2d,
@@ -319,7 +321,7 @@
       struct pipe_transfer *t;
       uint32_t *ptr;
       t = pipe_get_transfer(ctx, samptex,
-                            0, 0, 0, /* face, level, zslice */
+                            0, 0, /* level, layer */
                             PIPE_TRANSFER_READ,
                             0, 0, SIZE, SIZE); /* x, y, width, height */
 
@@ -338,8 +340,6 @@
    memset(&sv_template, 0, sizeof sv_template);
    sv_template.format = samptex->format;
    sv_template.texture = samptex;
-   sv_template.first_level = 0;
-   sv_template.last_level = 0;
    sv_template.swizzle_r = 0;
    sv_template.swizzle_g = 1;
    sv_template.swizzle_b = 2;
@@ -375,6 +375,7 @@
 {
    struct pipe_framebuffer_state fb;
    struct pipe_resource templat;
+   struct pipe_surface surf_tmpl;
    int i;
 
    /* It's hard to say whether window or screen should be created
@@ -401,6 +402,7 @@
    templat.width0 = WIDTH;
    templat.height0 = HEIGHT;
    templat.depth0 = 1;
+   templat.array_size = 1;
    templat.last_level = 0;
    templat.nr_samples = 1;
    templat.bind = (PIPE_BIND_RENDER_TARGET |
@@ -411,9 +413,12 @@
    if (rttex == NULL)
       exit(4);
 
-   surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
-                                  PIPE_BIND_RENDER_TARGET |
-                                  PIPE_BIND_DISPLAY_TARGET);
+   surf_tmpl.format = templat.format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = 0;
+   surf_tmpl.u.tex.first_layer = 0;
+   surf_tmpl.u.tex.last_layer = 0;
+   surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
    if (surf == NULL)
       exit(5);
 
diff --git a/src/gallium/tests/python/retrace/interpreter.py b/src/gallium/tests/python/retrace/interpreter.py
index 954a701..8451ade 100755
--- a/src/gallium/tests/python/retrace/interpreter.py
+++ b/src/gallium/tests/python/retrace/interpreter.py
@@ -251,14 +251,6 @@
     def texture_release(self, surface):
         pass
 
-    def get_tex_surface(self, texture, face, level, zslice, usage):
-        if texture is None:
-            return None
-        return texture.get_surface(face, level, zslice)
-    
-    def tex_surface_destroy(self, surface):
-        self.interpreter.unregister_object(surface)
-
     def tex_surface_release(self, surface):
         pass
 
@@ -282,7 +274,7 @@
     def fence_reference(self, dst, src):
         pass
     
-    def flush_frontbuffer(self, surface):
+    def flush_frontbuffer(self, resource):
         pass
 
 
@@ -627,7 +619,13 @@
         if self.zsbuf:
             if self.interpreter.options.all:
                 self.interpreter.present(self.real, self.zsbuf, "zsbuf")
-    
+    def create_surface(self, texture, level, layer, usage):
+        if texture is None:
+            return None
+        return texture.get_surface(level, layer)
+
+    def surface_destroy(self, surface):
+        self.interpreter.unregister_object(surface)
 
 class Interpreter(parser.TraceDumper):
     
diff --git a/src/gallium/tests/trivial/quad-tex.c b/src/gallium/tests/trivial/quad-tex.c
index cf88edc..92c5b4d 100644
--- a/src/gallium/tests/trivial/quad-tex.c
+++ b/src/gallium/tests/trivial/quad-tex.c
@@ -92,6 +92,7 @@
 
 static void init_prog(struct program *p)
 {
+	struct pipe_surface surf_tmpl;
 	/* create the software rasterizer */
 	p->screen = sw_screen_create(null_sw_create());
 	/* wrap the screen with any debugger */
@@ -141,6 +142,7 @@
 		tmplt.width0 = WIDTH;
 		tmplt.height0 = HEIGHT;
 		tmplt.depth0 = 1;
+		tmplt.array_size = 1;
 		tmplt.last_level = 0;
 		tmplt.bind = PIPE_BIND_RENDER_TARGET;
 
@@ -153,7 +155,6 @@
 		struct pipe_transfer *t;
 		struct pipe_resource t_tmplt;
 		struct pipe_sampler_view v_tmplt;
-		struct pipe_subresource sub;
 		struct pipe_box box;
 
 		memset(&t_tmplt, 0, sizeof(t_tmplt));
@@ -162,17 +163,17 @@
 		t_tmplt.width0 = 2;
 		t_tmplt.height0 = 2;
 		t_tmplt.depth0 = 1;
+		t_tmplt.array_size = 1;
 		t_tmplt.last_level = 0;
 		t_tmplt.bind = PIPE_BIND_RENDER_TARGET;
 
 		p->tex = p->screen->resource_create(p->screen, &t_tmplt);
 
-		memset(&sub, 0, sizeof(sub));
 		memset(&box, 0, sizeof(box));
 		box.width = 2;
 		box.height = 2;
 
-		t = p->pipe->get_transfer(p->pipe, p->tex, sub, PIPE_TRANSFER_WRITE, &box);
+		t = p->pipe->get_transfer(p->pipe, p->tex, 0, PIPE_TRANSFER_WRITE, &box);
 
 		ptr = p->pipe->transfer_map(p->pipe, t);
 		ptr[0] = 0xffff0000;
@@ -210,12 +211,17 @@
 	p->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
 	p->sampler.normalized_coords = 1;
 
+	surf_tmpl.format = templat.format;
+	surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+	surf_tmpl.u.tex.level = 0;
+	surf_tmpl.u.tex.first_layer = 0;
+	surf_tmpl.u.tex.last_layer = 0;
 	/* drawing destination */
 	memset(&p->framebuffer, 0, sizeof(p->framebuffer));
 	p->framebuffer.width = WIDTH;
 	p->framebuffer.height = HEIGHT;
 	p->framebuffer.nr_cbufs = 1;
-	p->framebuffer.cbufs[0] = p->screen->get_tex_surface(p->screen, p->target, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+	p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, p->target, &surf_tmpl);
 
 	/* viewport, depth isn't really needed */
 	{
diff --git a/src/gallium/tests/trivial/tri.c b/src/gallium/tests/trivial/tri.c
index 667a27b..37c1573 100644
--- a/src/gallium/tests/trivial/tri.c
+++ b/src/gallium/tests/trivial/tri.c
@@ -87,6 +87,7 @@
 
 static void init_prog(struct program *p)
 {
+	struct pipe_surface surf_tmpl;
 	/* create the software rasterizer */
 	p->screen = sw_screen_create(null_sw_create());
 	/* wrap the screen with any debugger */
@@ -132,6 +133,7 @@
 		tmplt.width0 = WIDTH;
 		tmplt.height0 = HEIGHT;
 		tmplt.depth0 = 1;
+		tmplt.array_size = 1;
 		tmplt.last_level = 0;
 		tmplt.bind = PIPE_BIND_RENDER_TARGET;
 
@@ -150,12 +152,17 @@
 	p->rasterizer.cull_face = PIPE_FACE_NONE;
 	p->rasterizer.gl_rasterization_rules = 1;
 
+	surf_tmpl.format = templat.format;
+	surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+	surf_tmpl.u.tex.level = 0;
+	surf_tmpl.u.tex.first_layer = 0;
+	surf_tmpl.u.tex.last_layer = 0;
 	/* drawing destination */
 	memset(&p->framebuffer, 0, sizeof(p->framebuffer));
 	p->framebuffer.width = WIDTH;
 	p->framebuffer.height = HEIGHT;
 	p->framebuffer.nr_cbufs = 1;
-	p->framebuffer.cbufs[0] = p->screen->get_tex_surface(p->screen, p->target, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+	p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, p->target, &surf_tmpl);
 
 	/* viewport, depth isn't really needed */
 	{
diff --git a/src/gallium/winsys/i965/xlib/xlib_i965.c b/src/gallium/winsys/i965/xlib/xlib_i965.c
index baadd6e..c22df66 100644
--- a/src/gallium/winsys/i965/xlib/xlib_i965.c
+++ b/src/gallium/winsys/i965/xlib/xlib_i965.c
@@ -42,6 +42,7 @@
 
 #include "i965/brw_winsys.h"
 #include "i965/brw_screen.h"
+#include "i965/brw_resource.h"
 #include "i965/brw_reg.h"
 #include "i965/brw_structs_dump.h"
 
@@ -421,25 +422,28 @@
 
 static void
 xlib_i965_display_surface(struct xmesa_buffer *xm_buffer,
-                          struct pipe_surface *surf)
+                          struct pipe_resource *resource,
+                          unsigned level, unsigned layer)
 {
-   struct brw_surface *surface = brw_surface(surf);
-   struct xlib_brw_buffer *bo = xlib_brw_buffer(surface->bo);
-
+   struct brw_texture *tex = brw_texture(resource);
+   struct xlib_brw_buffer *bo = xlib_brw_buffer(tex->bo);
+   /* not sure if the resource is really useful here but
+      since it was never implemented anyway... */
    if (BRW_DEBUG & DEBUG_WINSYS)
-      debug_printf("%s offset %x+%x sz %dx%d\n", __FUNCTION__, 
+      debug_printf("%s level %u layer %u offset %x base sz %dx%d\n", __FUNCTION__,
+                   level, layer,
                    bo->offset,
-                   surface->draw_offset,
-                   surf->width,
-                   surf->height);
+                   resource->width0,
+                   resource->height0);
 }
 
 static void
 xlib_i965_flush_frontbuffer(struct pipe_screen *screen,
-			    struct pipe_surface *surf,
-			    void *context_private)
+                            struct pipe_resource *resource,
+                            unsigned level, unsigned layer,
+                            void *context_private)
 {
-   xlib_i965_display_surface(NULL, surf);
+   xlib_i965_display_surface(NULL, resource, level, layer);
 }
 
 
diff --git a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
index bc2623e..8f9a908 100644
--- a/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
+++ b/src/gallium/winsys/sw/wrapper/wrapper_sw_winsys.c
@@ -93,9 +93,9 @@
    struct pipe_resource *tex = wdt->tex;
    struct pipe_transfer *tr;
 
-   tr = pipe_get_transfer(pipe, tex, 0, 0, 0,
-			  PIPE_TRANSFER_READ_WRITE,
-			  0, 0, wdt->width, wdt->height);
+   tr = pipe_get_transfer(pipe, tex, 0, 0,
+                          PIPE_TRANSFER_READ_WRITE,
+                          0, 0, wdt->width, wdt->height);
    if (!tr)
       return FALSE;
 
@@ -149,6 +149,8 @@
    templ.target = wsw->target;
    templ.width0 = width;
    templ.height0 = height;
+   templ.depth0 = 1;
+   templ.array_size = 1;
    templ.format = format;
    templ.bind = bind;
 
@@ -204,9 +206,9 @@
 
       assert(!wdt->transfer);
 
-      tr = pipe_get_transfer(pipe, tex, 0, 0, 0,
-			     PIPE_TRANSFER_READ_WRITE,
-			     0, 0, wdt->width, wdt->height);
+      tr = pipe_get_transfer(pipe, tex, 0, 0,
+                             PIPE_TRANSFER_READ_WRITE,
+                             0, 0, wdt->width, wdt->height);
       if (!tr)
          return NULL;
 
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
index 036bc60..2843b7b 100644
--- a/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -51,7 +51,7 @@
 update_renderbuffer_surface(struct st_context *st,
                             struct st_renderbuffer *strb)
 {
-   struct pipe_screen *screen = st->pipe->screen;
+   struct pipe_context *pipe = st->pipe;
    struct pipe_resource *resource = strb->rtt->pt;
    int rtt_width = strb->Base.Width;
    int rtt_height = strb->Base.Height;
@@ -65,15 +65,19 @@
       for (level = 0; level <= resource->last_level; level++) {
          if (u_minify(resource->width0, level) == rtt_width &&
              u_minify(resource->height0, level) == rtt_height) {
+            struct pipe_surface surf_tmpl;
+            memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+            surf_tmpl.format = resource->format;
+            surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+            surf_tmpl.u.tex.level = level;
+            surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
+            surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
 
             pipe_surface_reference(&strb->surface, NULL);
 
-            strb->surface = screen->get_tex_surface(screen,
-						    resource,
-						    strb->rtt_face,
-						    level,
-						    strb->rtt_slice,
-						    PIPE_BIND_RENDER_TARGET);
+            strb->surface = pipe->create_surface(pipe,
+                                                 resource,
+                                                 &surf_tmpl);
 #if 0
             printf("-- alloc new surface %d x %d into tex %p\n",
                    strb->surface->width, strb->surface->height,
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 6be0337..378b30e 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -122,8 +122,8 @@
    uint i, j;
 
    transfer = pipe_get_transfer(st_context(ctx)->pipe,
-					     pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
-					     0, 0, texSize, texSize);
+                                pt, 0, 0, PIPE_TRANSFER_WRITE,
+                                0, 0, texSize, texSize);
    dest = (uint *) pipe_transfer_map(pipe, transfer);
 
    /* Pack four 1D maps into a 2D texture:
diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c
index 6c5caf4..a76ae92 100644
--- a/src/mesa/state_tracker/st_cb_accum.c
+++ b/src/mesa/state_tracker/st_cb_accum.c
@@ -138,10 +138,10 @@
       debug_printf("%s: fallback processing\n", __FUNCTION__);
 
    color_trans = pipe_get_transfer(st->pipe,
-						color_strb->texture,
-						0, 0, 0,
-						PIPE_TRANSFER_READ, xpos, ypos,
-						width, height);
+                                   color_strb->texture,
+                                   0, 0,
+                                   PIPE_TRANSFER_READ, xpos, ypos,
+                                   width, height);
 
    buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
@@ -187,9 +187,9 @@
       debug_printf("%s: fallback processing\n", __FUNCTION__);
 
    color_trans = pipe_get_transfer(st->pipe, color_strb->texture,
-						0, 0, 0,
-						PIPE_TRANSFER_READ, xpos, ypos,
-						width, height);
+                                   0, 0,
+                                   PIPE_TRANSFER_READ, xpos, ypos,
+                                   width, height);
 
    buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
@@ -241,12 +241,12 @@
       usage = PIPE_TRANSFER_READ_WRITE;
    else
       usage = PIPE_TRANSFER_WRITE;
-   
+
    color_trans = pipe_get_transfer(st_context(ctx)->pipe,
-						color_strb->texture, 0, 0, 0,
-						usage,
-						xpos, ypos,
-						width, height);
+                                   color_strb->texture, 0, 0,
+                                   usage,
+                                   xpos, ypos,
+                                   width, height);
 
    if (usage & PIPE_TRANSFER_READ)
       pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 3c0ee6c..f08697f 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -283,9 +283,9 @@
       return NULL;
    }
 
-   transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 0,
-					   PIPE_TRANSFER_WRITE,
-					   0, 0, width, height);
+   transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
+                                PIPE_TRANSFER_WRITE,
+                                0, 0, width, height);
 
    dest = pipe_transfer_map(pipe, transfer);
 
@@ -585,10 +585,10 @@
    /* Map the texture transfer.
     * Subsequent glBitmap calls will write into the texture image.
     */
-   cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0, 0,
-					       PIPE_TRANSFER_WRITE, 0, 0,
-					       BITMAP_CACHE_WIDTH,
-					       BITMAP_CACHE_HEIGHT);
+   cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0,
+                                    PIPE_TRANSFER_WRITE, 0, 0,
+                                    BITMAP_CACHE_WIDTH,
+                                    BITMAP_CACHE_HEIGHT);
    cache->buffer = pipe_transfer_map(pipe, cache->trans);
 
    /* init image to all 0xff */
diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c
index af41835..06cee52 100644
--- a/src/mesa/state_tracker/st_cb_blit.c
+++ b/src/mesa/state_tracker/st_cb_blit.c
@@ -115,17 +115,14 @@
             st_texture_object(srcAtt->Texture);
          struct st_renderbuffer *dstRb =
             st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
-         struct pipe_subresource srcSub;
          struct pipe_surface *dstSurf = dstRb->surface;
 
          if (!srcObj->pt)
             return;
 
-         srcSub.face = srcAtt->CubeMapFace;
-         srcSub.level = srcAtt->TextureLevel;
-
-         util_blit_pixels(st->blit, srcObj->pt, srcSub,
-                          srcX0, srcY0, srcX1, srcY1, srcAtt->Zoffset,
+         util_blit_pixels(st->blit, srcObj->pt, srcAtt->TextureLevel,
+                          srcX0, srcY0, srcX1, srcY1,
+                          srcAtt->Zoffset + srcAtt->CubeMapFace,
                           dstSurf, dstX0, dstY0, dstX1, dstY1,
                           0.0, pFilter);
       }
@@ -136,14 +133,11 @@
             st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
          struct pipe_surface *srcSurf = srcRb->surface;
          struct pipe_surface *dstSurf = dstRb->surface;
-         struct pipe_subresource srcSub;
-
-         srcSub.face = srcSurf->face;
-         srcSub.level = srcSurf->level;
 
          util_blit_pixels(st->blit,
-                          srcRb->texture, srcSub, srcX0, srcY0, srcX1, srcY1,
-                          srcSurf->zslice,
+                          srcRb->texture, srcSurf->u.tex.level,
+                          srcX0, srcY0, srcX1, srcY1,
+                          srcSurf->u.tex.first_layer,
                           dstSurf, dstX0, dstY0, dstX1, dstY1,
                           0.0, pFilter);
       }
@@ -176,11 +170,11 @@
          /* Blitting depth and stencil values between combined
           * depth/stencil buffers.  This is the ideal case for such buffers.
           */
-         util_blit_pixels(st->blit, srcDepthRb->texture,
-                          u_subresource(srcDepthRb->surface->face,
-                                        srcDepthRb->surface->level),
+         util_blit_pixels(st->blit,
+                          srcDepthRb->texture,
+                          srcDepthRb->surface->u.tex.level,
                           srcX0, srcY0, srcX1, srcY1,
-                          srcDepthRb->surface->zslice,
+                          srcDepthRb->surface->u.tex.first_layer,
                           dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                           0.0, pFilter);
       }
@@ -189,10 +183,9 @@
 
          if (mask & GL_DEPTH_BUFFER_BIT) {
             util_blit_pixels(st->blit, srcDepthRb->texture,
-                             u_subresource(srcDepthRb->surface->face,
-                                           srcDepthRb->surface->level),
+                             srcDepthRb->surface->u.tex.level,
                              srcX0, srcY0, srcX1, srcY1,
-                             srcDepthRb->surface->zslice,
+                             srcDepthRb->surface->u.tex.first_layer,
                              dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                              0.0, pFilter);
          }
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index d80c068..c978602 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -427,9 +427,9 @@
       /* we'll do pixel transfer in a fragment shader */
       ctx->_ImageTransferState = 0x0;
 
-      transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 0,
-					      PIPE_TRANSFER_WRITE, 0, 0,
-					      width, height);
+      transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
+                                   PIPE_TRANSFER_WRITE, 0, 0,
+                                   width, height);
 
       /* map texture transfer */
       dest = pipe_transfer_map(pipe, transfer);
@@ -763,9 +763,9 @@
    else
       usage = PIPE_TRANSFER_WRITE;
 
-   pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, 0,
-				       usage, x, y,
-				       width, height);
+   pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0,
+                                     usage, x, y,
+                                     width, height);
 
    stmap = pipe_transfer_map(pipe, pt);
 
@@ -1025,15 +1025,15 @@
       usage = PIPE_TRANSFER_READ_WRITE;
    else
       usage = PIPE_TRANSFER_WRITE;
-   
+
    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
       dsty = rbDraw->Base.Height - dsty - height;
    }
 
    ptDraw = pipe_get_transfer(st_context(ctx)->pipe,
-					   rbDraw->texture, 0, 0, 0,
-					   usage, dstx, dsty,
-					   width, height);
+                              rbDraw->texture, 0, 0,
+                              usage, dstx, dsty,
+                              width, height);
 
    assert(util_format_get_blockwidth(ptDraw->resource->format) == 1);
    assert(util_format_get_blockheight(ptDraw->resource->format) == 1);
@@ -1209,27 +1209,24 @@
    /* Make temporary texture which is a copy of the src region.
     */
    if (srcFormat == texFormat) {
-      struct pipe_subresource srcsub, dstsub;
-      srcsub.face = 0;
-      srcsub.level = 0;
-      dstsub.face = 0;
-      dstsub.level = 0;
-      /* copy source framebuffer surface into mipmap/texture */
+      struct pipe_box src_box;
+      u_box_2d(readX, readY, readW, readH, &src_box);
+    /* copy source framebuffer surface into mipmap/texture */
       pipe->resource_copy_region(pipe,
                                  pt,                                /* dest tex */
-                                 dstsub,
+                                 0,
                                  pack.SkipPixels, pack.SkipRows, 0, /* dest pos */
                                  rbRead->texture,                   /* src tex */
-                                 srcsub,
-                                 readX, readY, 0, readW, readH);    /* src region */
+                                 0,
+                                 &src_box);
 
    }
    else {
       /* CPU-based fallback/conversion */
       struct pipe_transfer *ptRead =
-         pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, 0,
-                                        PIPE_TRANSFER_READ,
-                                        readX, readY, readW, readH);
+         pipe_get_transfer(st->pipe, rbRead->texture, 0, 0,
+                           PIPE_TRANSFER_READ,
+                           readX, readY, readW, readH);
       struct pipe_transfer *ptTex;
       enum pipe_transfer_usage transfer_usage;
 
@@ -1241,8 +1238,8 @@
       else
          transfer_usage = PIPE_TRANSFER_WRITE;
 
-      ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, 0, transfer_usage,
-                                             0, 0, width, height);
+      ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage,
+                                0, 0, width, height);
 
       /* copy image from ptRead surface to ptTex surface */
       if (type == GL_COLOR) {
diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c
index 9425f07..cd718a3 100644
--- a/src/mesa/state_tracker/st_cb_fbo.c
+++ b/src/mesa/state_tracker/st_cb_fbo.c
@@ -52,6 +52,7 @@
 
 #include "util/u_format.h"
 #include "util/u_inlines.h"
+#include "util/u_surface.h"
 
 
 /**
@@ -65,9 +66,11 @@
                               GLuint width, GLuint height)
 {
    struct st_context *st = st_context(ctx);
+   struct pipe_context *pipe = st->pipe;
    struct pipe_screen *screen = st->pipe->screen;
    struct st_renderbuffer *strb = st_renderbuffer(rb);
    enum pipe_format format;
+   struct pipe_surface surf_tmpl;
 
    if (strb->format != PIPE_FORMAT_NONE)
       format = strb->format;
@@ -113,6 +116,7 @@
       template.width0 = width;
       template.height0 = height;
       template.depth0 = 1;
+      template.array_size = 1;
       template.last_level = 0;
       template.nr_samples = rb->NumSamples;
       if (util_format_is_depth_or_stencil(format)) {
@@ -120,7 +124,7 @@
       }
       else {
          template.bind = (PIPE_BIND_DISPLAY_TARGET |
-			  PIPE_BIND_RENDER_TARGET);
+                          PIPE_BIND_RENDER_TARGET);
       }
 
       strb->texture = screen->resource_create(screen, &template);
@@ -128,10 +132,11 @@
       if (!strb->texture) 
          return FALSE;
 
-      strb->surface = screen->get_tex_surface(screen,
-                                              strb->texture,
-                                              0, 0, 0,
-                                              template.bind);
+      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+      u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
+      strb->surface = pipe->create_surface(pipe,
+                                           strb->texture,
+                                           &surf_tmpl);
       if (strb->surface) {
          assert(strb->surface->texture);
          assert(strb->surface->format);
@@ -327,12 +332,12 @@
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
-   struct pipe_screen *screen = pipe->screen;
    struct st_renderbuffer *strb;
    struct gl_renderbuffer *rb;
    struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
    struct st_texture_object *stObj;
    const struct gl_texture_image *texImage;
+   struct pipe_surface surf_tmpl;
 
    /* When would this fail?  Perhaps assert? */
    if (!pt) 
@@ -381,12 +386,15 @@
    assert(strb->rtt_level <= strb->texture->last_level);
 
    /* new surface for rendering into the texture */
-   strb->surface = screen->get_tex_surface(screen,
-                                           strb->texture,
-                                           strb->rtt_face,
-                                           strb->rtt_level,
-                                           strb->rtt_slice,
-                                           PIPE_BIND_RENDER_TARGET);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   surf_tmpl.format = strb->texture->format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = strb->rtt_level;
+   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
+   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
+   strb->surface = pipe->create_surface(pipe,
+                                        strb->texture,
+                                        &surf_tmpl);
 
    strb->format = pt->format;
 
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index bcd46ac..620da07 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -80,7 +80,7 @@
    /* Create a read transfer from the renderbuffer's texture */
 
    pt = pipe_get_transfer(pipe, strb->texture,
-                          0, 0, 0,  /* face, level, zslice */
+                          0, 0,
                           PIPE_TRANSFER_READ,
                           x, y, width, height);
 
@@ -236,7 +236,7 @@
       }
 
       trans = pipe_get_transfer(pipe, strb->texture,
-                                0, 0, 0,  /* face, level, zslice */
+                                0, 0,
                                 PIPE_TRANSFER_READ,
                                 x, y, width, height);
       if (!trans) {
@@ -400,7 +400,7 @@
 
    /* Create a read transfer from the renderbuffer's texture */
    trans = pipe_get_transfer(pipe, strb->texture,
-                             0, 0, 0,  /* face, level, zslice */
+                             0, 0,
                              PIPE_TRANSFER_READ,
                              x, y, width, height);
 
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 15e69e1..d0fb630 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -63,7 +63,7 @@
 #include "util/u_surface.h"
 #include "util/u_sampler.h"
 #include "util/u_math.h"
-
+#include "util/u_box.h"
 
 #define DBG if (0) printf
 
@@ -431,7 +431,7 @@
    struct pipe_resource *src_tex;
    struct pipe_sampler_view view_templ;
    struct pipe_sampler_view *src_view;
-   struct pipe_surface *dst_surface;
+   struct pipe_surface *dst_surface, surf_tmpl;
    struct pipe_transfer *tex_xfer;
    void *map;
 
@@ -441,9 +441,13 @@
    }
 
    /* get destination surface (in the compressed texture) */
-   dst_surface = screen->get_tex_surface(screen, stImage->pt,
-                                         stImage->face, stImage->level, 0,
-                                         0 /* flags */);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   surf_tmpl.format = stImage->pt->format;
+   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+   surf_tmpl.u.tex.level = stImage->level;
+   surf_tmpl.u.tex.first_layer = stImage->face;
+   surf_tmpl.u.tex.last_layer = stImage->face;
+   dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl);
    if (!dst_surface) {
       /* can't render into this format (or other problem) */
       return GL_FALSE;
@@ -464,6 +468,7 @@
    templ.width0 = width;
    templ.height0 = height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.last_level = 0;
    templ.usage = PIPE_USAGE_DEFAULT;
    templ.bind = PIPE_BIND_SAMPLER_VIEW;
@@ -475,9 +480,9 @@
    /* Put user's tex data into the temporary texture
     */
    tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex,
-					     0, 0, 0, /* face, level are zero */
-					     PIPE_TRANSFER_WRITE,
-					     0, 0, width, height); /* x, y, w, h */
+                                0, 0, /* layer, level are zero */
+                                PIPE_TRANSFER_WRITE,
+                                0, 0, width, height); /* x, y, w, h */
    map = pipe_transfer_map(pipe, tex_xfer);
 
    _mesa_texstore(ctx, 2, GL_RGBA, mesa_format,
@@ -857,7 +862,6 @@
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
-   struct pipe_screen *screen = pipe->screen;
    struct st_texture_image *stImage = st_texture_image(texImage);
    struct st_texture_object *stObj = st_texture_object(texObj);
    struct pipe_sampler_view *src_view =
@@ -871,7 +875,7 @@
 		    PIPE_BIND_TRANSFER_READ);
 
    /* create temp / dest surface */
-   if (!util_create_rgba_surface(screen, width, height, bind,
+   if (!util_create_rgba_surface(pipe, width, height, bind,
                                  &dst_texture, &dst_surface)) {
       _mesa_problem(ctx, "util_create_rgba_surface() failed "
                     "in decompress_with_blit()");
@@ -891,9 +895,9 @@
 
    /* map the dst_surface so we can read from it */
    tex_xfer = pipe_get_transfer(st_context(ctx)->pipe,
-					     dst_texture, 0, 0, 0,
-					     PIPE_TRANSFER_READ,
-					     0, 0, width, height);
+                                dst_texture, 0, 0,
+                                PIPE_TRANSFER_READ,
+                                0, 0, width, height);
 
    pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);
 
@@ -1310,7 +1314,7 @@
    struct pipe_transfer *src_trans;
    GLvoid *texDest;
    enum pipe_transfer_usage transfer_usage;
-   
+
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
 
@@ -1321,11 +1325,11 @@
    }
 
    src_trans = pipe_get_transfer(st_context(ctx)->pipe,
-					       strb->texture,
-					       0, 0, 0,
-					       PIPE_TRANSFER_READ,
-					       srcX, srcY,
-					       width, height);
+                                 strb->texture,
+                                 0, 0,
+                                 PIPE_TRANSFER_READ,
+                                 srcX, srcY,
+                                 width, height);
 
    if ((baseFormat == GL_DEPTH_COMPONENT ||
         baseFormat == GL_DEPTH_STENCIL) &&
@@ -1334,7 +1338,8 @@
    else
       transfer_usage = PIPE_TRANSFER_WRITE;
 
-   texDest = st_texture_image_map(st, stImage, 0, transfer_usage,
+   /* XXX this used to ignore destZ param */
+   texDest = st_texture_image_map(st, stImage, destZ, transfer_usage,
                                   destX, destY, width, height);
 
    if (baseFormat == GL_DEPTH_COMPONENT ||
@@ -1592,27 +1597,23 @@
 
       if (matching_base_formats &&
           src_format == dest_format &&
-          !do_flip) 
+          !do_flip)
       {
          /* use surface_copy() / blit */
-         struct pipe_subresource subdst, subsrc;
-         subdst.face = stImage->face;
-         subdst.level = stImage->level;
-         subsrc.face = strb->surface->face;
-         subsrc.level = strb->surface->level;
+         struct pipe_box src_box;
+         u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
+                         width, height, &src_box);
 
          /* for resource_copy_region(), y=0=top, always */
          pipe->resource_copy_region(pipe,
                                     /* dest */
                                     stImage->pt,
-                                    subdst,
-                                    destX, destY, destZ,
+                                    stImage->level,
+                                    destX, destY, destZ + stImage->face,
                                     /* src */
                                     strb->texture,
-                                    subsrc,
-                                    srcX, srcY, strb->surface->zslice,
-                                    /* size */
-                                    width, height);
+                                    strb->surface->u.tex.level,
+                                    &src_box);
          use_fallback = GL_FALSE;
       }
       else if (format_writemask &&
@@ -1628,12 +1629,16 @@
                                            0)) {
          /* draw textured quad to do the copy */
          GLint srcY0, srcY1;
-         struct pipe_subresource subsrc;
+         struct pipe_surface surf_tmpl;
+         memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+         surf_tmpl.format = stImage->pt->format;
+         surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
+         surf_tmpl.u.tex.level = stImage->level;
+         surf_tmpl.u.tex.first_layer = stImage->face + destZ;
+         surf_tmpl.u.tex.last_layer = stImage->face + destZ;
 
-         dest_surface = screen->get_tex_surface(screen, stImage->pt,
-                                                stImage->face, stImage->level,
-                                                destZ,
-                                                PIPE_BIND_RENDER_TARGET);
+         dest_surface = pipe->create_surface(pipe, stImage->pt,
+                                             &surf_tmpl);
 
          if (do_flip) {
             srcY1 = strb->Base.Height - srcY - height;
@@ -1643,15 +1648,13 @@
             srcY0 = srcY;
             srcY1 = srcY0 + height;
          }
-         subsrc.face = strb->surface->face;
-         subsrc.level = strb->surface->level;
 
          util_blit_pixels_writemask(st->blit,
                                     strb->texture,
-                                    subsrc,
+                                    strb->surface->u.tex.level,
                                     srcX, srcY0,
                                     srcX + width, srcY1,
-                                    strb->surface->zslice,
+                                    strb->surface->u.tex.first_layer,
                                     dest_surface,
                                     destX, destY,
                                     destX + width, destY + height,
diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c
index 1fc4f40..2472c0b 100644
--- a/src/mesa/state_tracker/st_gen_mipmap.c
+++ b/src/mesa/state_tracker/st_gen_mipmap.c
@@ -79,11 +79,15 @@
    const uint face = _mesa_tex_target_to_face(target);
 
    assert(psv->texture == stObj->pt);
-   assert(target != GL_TEXTURE_3D); /* not done yet */
+#if 0
+   assert(target != GL_TEXTURE_3D); /* implemented but untested */
+#endif
 
    /* check if we can render in the texture's format */
-   if (!screen->is_format_supported(screen, psv->format, psv->texture->target, 0,
-                                    PIPE_BIND_RENDER_TARGET, 0)) {
+   /* XXX should probably kill this and always use util_gen_mipmap
+      since this implements a sw fallback as well */
+   if (!screen->is_format_supported(screen, psv->format, psv->texture->target,
+                                    0, PIPE_BIND_RENDER_TARGET, 0)) {
       return FALSE;
    }
 
@@ -161,12 +165,12 @@
    struct pipe_resource *pt = st_get_texobj_resource(texObj);
    const uint baseLevel = texObj->BaseLevel;
    const uint lastLevel = pt->last_level;
-   const uint face = _mesa_tex_target_to_face(target), zslice = 0;
+   const uint face = _mesa_tex_target_to_face(target);
    uint dstLevel;
    GLenum datatype;
    GLuint comps;
    GLboolean compressed;
-   
+
    if (ST_DEBUG & DEBUG_FALLBACK)
       debug_printf("%s: fallback processing\n", __FUNCTION__);
 
@@ -198,16 +202,15 @@
       ubyte *dstData;
       int srcStride, dstStride;
 
-      srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, face,
-						srcLevel, zslice,
-						PIPE_TRANSFER_READ, 0, 0,
-                                                srcWidth, srcHeight);
-						
+      srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, srcLevel,
+                                   face,
+                                   PIPE_TRANSFER_READ, 0, 0,
+                                   srcWidth, srcHeight);
 
-      dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, face,
-						dstLevel, zslice,
-						PIPE_TRANSFER_WRITE, 0, 0,
-						dstWidth, dstHeight);
+      dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, dstLevel,
+                                   face,
+                                   PIPE_TRANSFER_WRITE, 0, 0,
+                                   dstWidth, dstHeight);
 
       srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans);
       dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans);
@@ -215,6 +218,8 @@
       srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format);
       dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format);
 
+     /* this cannot work correctly for 3d since it does
+        not respect layerStride. */
       if (compressed) {
          const enum pipe_format format = pt->format;
          const uint bw = util_format_get_blockwidth(format);
@@ -372,6 +377,8 @@
     * use the software fallback.
     */
    if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {
+      /* since the util code actually also has a fallback, should
+         probably make it never fail and kill this */
       fallback_generate_mipmap(ctx, target, texObj);
    }
 
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 05733e8..0307b48 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -34,6 +34,7 @@
 #include "util/u_pointer.h"
 #include "util/u_inlines.h"
 #include "util/u_atomic.h"
+#include "util/u_surface.h"
 
 #include "main/mtypes.h"
 #include "main/context.h"
@@ -142,7 +143,7 @@
 static void
 st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
 {
-   struct pipe_screen *screen = st->pipe->screen;
+   struct pipe_context *pipe = st->pipe;
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
    uint width, height;
    unsigned i;
@@ -160,7 +161,7 @@
 
    for (i = 0; i < stfb->num_statts; i++) {
       struct st_renderbuffer *strb;
-      struct pipe_surface *ps;
+      struct pipe_surface *ps, surf_tmpl;
       gl_buffer_index idx;
 
       if (!textures[i])
@@ -179,8 +180,10 @@
          continue;
       }
 
-      ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0,
-				   PIPE_BIND_RENDER_TARGET);
+      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+      u_surface_default_template(&surf_tmpl, textures[i],
+                                 PIPE_BIND_RENDER_TARGET);
+      ps = pipe->create_surface(pipe, textures[i], &surf_tmpl);
       if (ps) {
          pipe_surface_reference(&strb->surface, ps);
          pipe_resource_reference(&strb->texture, ps->texture);
@@ -813,6 +816,7 @@
 
 /**
  * Return the surface of an EGLImage.
+ * FIXME: I think this should operate on resources, not surfaces
  */
 struct pipe_surface *
 st_manager_get_egl_image_surface(struct st_context *st,
@@ -821,7 +825,7 @@
    struct st_manager *smapi =
       (struct st_manager *) st->iface.st_context_private;
    struct st_egl_image stimg;
-   struct pipe_surface *ps;
+   struct pipe_surface *ps, surf_tmpl;
 
    if (!smapi || !smapi->get_egl_image)
       return NULL;
@@ -830,8 +834,13 @@
    if (!smapi->get_egl_image(smapi, eglimg, &stimg))
       return NULL;
 
-   ps = smapi->screen->get_tex_surface(smapi->screen,
-         stimg.texture, stimg.face, stimg.level, stimg.zslice, usage);
+   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+   surf_tmpl.format = stimg.texture->format;
+   surf_tmpl.usage = usage;
+   surf_tmpl.u.tex.level = stimg.level;
+   surf_tmpl.u.tex.first_layer = stimg.layer;
+   surf_tmpl.u.tex.last_layer = stimg.layer;
+   ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl);
    pipe_resource_reference(&stimg.texture, NULL);
 
    return ps;
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index c6cf2ba..155ea39 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -84,6 +84,7 @@
    pt.width0 = width0;
    pt.height0 = height0;
    pt.depth0 = depth0;
+   pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1);
    pt.usage = PIPE_USAGE_DEFAULT;
    pt.bind = bind;
    pt.flags = 0;
@@ -136,7 +137,7 @@
  */
 GLubyte *
 st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
-		     GLuint zoffset, enum pipe_transfer_usage usage,
+                     GLuint zoffset, enum pipe_transfer_usage usage,
                      GLuint x, GLuint y, GLuint w, GLuint h)
 {
    struct pipe_context *pipe = st->pipe;
@@ -144,9 +145,9 @@
 
    DBG("%s \n", __FUNCTION__);
 
-   stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->face,
-						    stImage->level, zoffset,
-						    usage, x, y, w, h);
+   stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->level,
+                                         stImage->face + zoffset,
+                                         usage, x, y, w, h);
 
    if (stImage->transfer)
       return pipe_transfer_map(pipe, stImage->transfer);
@@ -219,10 +220,10 @@
    DBG("%s\n", __FUNCTION__);
 
    for (i = 0; i < depth; i++) {
-      dst_transfer = pipe_get_transfer(st->pipe, dst, face, level, i,
-						  PIPE_TRANSFER_WRITE, 0, 0,
-						  u_minify(dst->width0, level),
-                                                  u_minify(dst->height0, level));
+      dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i,
+                                       PIPE_TRANSFER_WRITE, 0, 0,
+                                       u_minify(dst->width0, level),
+                                       u_minify(dst->height0, level));
 
       st_surface_data(pipe, dst_transfer,
 		      0, 0,                             /* dstx, dsty */
@@ -230,7 +231,7 @@
 		      src_row_stride,
 		      0, 0,                             /* source x, y */
 		      u_minify(dst->width0, level),
-                      u_minify(dst->height0, level));      /* width, height */
+                      u_minify(dst->height0, level));    /* width, height */
 
       pipe->transfer_destroy(pipe, dst_transfer);
 
@@ -245,14 +246,10 @@
 static void
 print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
 {
-   struct pipe_subresource rect;
    struct pipe_transfer *xfer;
    struct pipe_box region;
    ubyte *map;
 
-   rect.face = 0;
-   rect.level = 0;
-
    region.x = src->width0 / 2;
    region.y = src->height0 / 2;
    region.z = 0;
@@ -260,7 +257,7 @@
    region.height = 1;
    region.depth = 1;
 
-   xfer = pipe->get_transfer(pipe, src, rect, PIPE_TRANSFER_READ, &region);
+   xfer = pipe->get_transfer(pipe, src, 0, PIPE_TRANSFER_READ, &region);
    map = pipe->transfer_map(pipe, xfer);
 
    printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
@@ -282,22 +279,26 @@
                       struct pipe_resource *src, GLuint srcLevel,
                       GLuint face)
 {
-   GLuint width = u_minify(dst->width0, dstLevel); 
-   GLuint height = u_minify(dst->height0, dstLevel); 
-   GLuint depth = u_minify(dst->depth0, dstLevel); 
-   struct pipe_subresource dstsub, srcsub;
+   GLuint width = u_minify(dst->width0, dstLevel);
+   GLuint height = u_minify(dst->height0, dstLevel);
+   GLuint depth = u_minify(dst->depth0, dstLevel);
+   struct pipe_box src_box;
    GLuint i;
 
    assert(u_minify(src->width0, srcLevel) == width);
    assert(u_minify(src->height0, srcLevel) == height);
    assert(u_minify(src->depth0, srcLevel) == depth);
 
-   dstsub.face = face;
-   dstsub.level = dstLevel;
-   srcsub.face = face;
-   srcsub.level = srcLevel;
+   src_box.x = 0;
+   src_box.y = 0;
+   src_box.width = width;
+   src_box.height = height;
+   src_box.depth = 1;
    /* Loop over 3D image slices */
-   for (i = 0; i < depth; i++) {
+   /* could (and probably should) use "true" 3d box here -
+      but drivers can't quite handle it yet */
+   for (i = face; i < face + depth; i++) {
+      src_box.z = i;
 
       if (0)  {
          print_center_pixel(pipe, src);
@@ -305,12 +306,11 @@
 
       pipe->resource_copy_region(pipe,
                                  dst,
-                                 dstsub,
+                                 dstLevel,
                                  0, 0, i,/* destX, Y, Z */
                                  src,
-                                 srcsub,
-                                 0, 0, i,/* srcX, Y, Z */
-                                 width, height);
+                                 srcLevel,
+                                 &src_box);
    }
 }