+ else {
+ /* regular texture */
+ align_free(lpt->data);
+ }
+
+ FREE(lpt);
+}
+
+
+/**
+ * Map a texture. Without any synchronization.
+ */
+void *
+llvmpipe_texture_map(struct pipe_texture *texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice)
+{
+ struct llvmpipe_texture *lpt = llvmpipe_texture(texture);
+ uint8_t *map;
+
+ if (lpt->dt) {
+ /* display target */
+ struct llvmpipe_screen *screen = llvmpipe_screen(texture->screen);
+ struct sw_winsys *winsys = screen->winsys;
+ const unsigned usage = PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+
+ assert(face == 0);
+ assert(level == 0);
+ assert(zslice == 0);
+
+ /* FIXME: keep map count? */
+ map = winsys->displaytarget_map(winsys, lpt->dt, usage);
+ }
+ else {
+ /* regular texture */
+ unsigned offset;
+ unsigned stride;
+
+ map = lpt->data;
+
+ assert(level < LP_MAX_TEXTURE_2D_LEVELS);
+
+ offset = lpt->level_offset[level];
+ stride = lpt->stride[level];
+
+ /* XXX shouldn't that rather be
+ tex_height = align(u_minify(texture->height0, level), 2)
+ to account for alignment done in llvmpipe_texture_layout ?
+ */
+ if (texture->target == PIPE_TEXTURE_CUBE) {
+ unsigned tex_height = u_minify(texture->height0, level);
+ offset += face * util_format_get_nblocksy(texture->format, tex_height) * stride;
+ }
+ else if (texture->target == PIPE_TEXTURE_3D) {
+ unsigned tex_height = u_minify(texture->height0, level);
+ offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * stride;
+ }
+ else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
+
+ map += offset;
+ }
+
+ return map;
+}
+
+
+/**
+ * Unmap a texture. Without any synchronization.
+ */
+void
+llvmpipe_texture_unmap(struct pipe_texture *texture,
+ unsigned face,
+ unsigned level,
+ unsigned zslice)
+{
+ struct llvmpipe_texture *lpt = llvmpipe_texture(texture);