[Mesa-dev] [PATCH] panfrost: Preliminary work for mipmaps

Alyssa Rosenzweig alyssa at rosenzweig.io
Sun Mar 24 03:46:15 UTC 2019


This patch refactors a substantial amount of code in preparation for
mipmaps. In particular, we know have a correct slice abstraction based
on offsets; cpu/gpu are no longer arbitrary pointers. We additionally
shuffle around other code to accompany these changes and cleanup how
tiled textures are handled, while drawing some attention to the blit
code.

Mipmaps are still disabled at this point, as autogeneration is not yet
implemented; enabling as-is would cause regressions.

Signed-off-by: Alyssa Rosenzweig <alyssa at rosenzweig.io>
---
 src/gallium/drivers/panfrost/pan_context.c  |  49 ++---
 src/gallium/drivers/panfrost/pan_drm.c      |  16 +-
 src/gallium/drivers/panfrost/pan_mfbd.c     |  10 +-
 src/gallium/drivers/panfrost/pan_resource.c | 209 +++++++++-----------
 src/gallium/drivers/panfrost/pan_resource.h |  39 ++--
 src/gallium/drivers/panfrost/pan_sfbd.c     |   4 +-
 src/gallium/drivers/panfrost/pan_swizzle.c  |  37 ++--
 src/gallium/drivers/panfrost/pan_swizzle.h  |   6 +-
 8 files changed, 163 insertions(+), 207 deletions(-)

diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index 19cdb6c0444..69120a8ad84 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -85,8 +85,8 @@ panfrost_enable_afbc(struct panfrost_context *ctx, struct panfrost_resource *rsr
 
         /* Compressed textured reads use a tagged pointer to the metadata */
 
-        rsrc->bo->gpu[0] = rsrc->bo->afbc_slab.gpu | (ds ? 0 : 1);
-        rsrc->bo->cpu[0] = rsrc->bo->afbc_slab.cpu;
+        rsrc->bo->gpu = rsrc->bo->afbc_slab.gpu | (ds ? 0 : 1);
+        rsrc->bo->cpu = rsrc->bo->afbc_slab.cpu;
 }
 
 static void
@@ -772,10 +772,10 @@ panfrost_emit_vertex_data(struct panfrost_context *ctx)
                  * rsrc->gpu. However, attribute buffers must be 64 aligned. If
                  * it is not, for now we have to duplicate the buffer. */
 
-                mali_ptr effective_address = (rsrc->bo->gpu[0] + buf->buffer_offset);
+                mali_ptr effective_address = (rsrc->bo->gpu + buf->buffer_offset);
 
                 if (effective_address & 0x3F) {
-                        attrs[i].elements = panfrost_upload_transient(ctx, rsrc->bo->cpu[0] + buf->buffer_offset, attrs[i].size) | 1;
+                        attrs[i].elements = panfrost_upload_transient(ctx, rsrc->bo->cpu + buf->buffer_offset, attrs[i].size) | 1;
                 } else {
                         attrs[i].elements = effective_address | 1;
                 }
@@ -1018,31 +1018,12 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data)
                                 struct panfrost_resource *rsrc = (struct panfrost_resource *) tex_rsrc;
 
                                 /* Inject the address in. */
-                                for (int l = 0; l < (tex_rsrc->last_level + 1); ++l)
-                                        ctx->sampler_views[t][i]->hw.swizzled_bitmaps[l] = rsrc->bo->gpu[l];
-
-                                /* Workaround maybe-errata (?) with non-mipmaps */
-                                int s = ctx->sampler_views[t][i]->hw.nr_mipmap_levels;
-
-                                if (!rsrc->bo->is_mipmap) {
-                                        if (ctx->is_t6xx) {
-                                                /* HW ERRATA, not needed after t6XX */
-                                                ctx->sampler_views[t][i]->hw.swizzled_bitmaps[1] = rsrc->bo->gpu[0];
-
-                                                ctx->sampler_views[t][i]->hw.unknown3A = 1;
-                                        }
-
-                                        ctx->sampler_views[t][i]->hw.nr_mipmap_levels = 0;
+                                for (int l = 0; l <= tex_rsrc->last_level; ++l) {
+                                        ctx->sampler_views[t][i]->hw.swizzled_bitmaps[l] =
+                                                rsrc->bo->gpu + rsrc->bo->slices[l].offset;
                                 }
 
                                 trampolines[i] = panfrost_upload_transient(ctx, &ctx->sampler_views[t][i]->hw, sizeof(struct mali_texture_descriptor));
-
-                                /* Restore */
-                                ctx->sampler_views[t][i]->hw.nr_mipmap_levels = s;
-
-				if (ctx->is_t6xx) {
-					ctx->sampler_views[t][i]->hw.unknown3A = 0;
-				}
                         }
 
                         mali_ptr trampoline = panfrost_upload_transient(ctx, trampolines, sizeof(uint64_t) * ctx->sampler_view_count[t]);
@@ -1362,7 +1343,7 @@ panfrost_get_index_buffer_raw(const struct pipe_draw_info *info)
                 return (const uint8_t *) info->index.user;
         } else {
                 struct panfrost_resource *rsrc = (struct panfrost_resource *) (info->index.resource);
-                return (const uint8_t *) rsrc->bo->cpu[0];
+                return (const uint8_t *) rsrc->bo->cpu;
         }
 }
 
@@ -1378,7 +1359,7 @@ panfrost_get_index_buffer_mapped(struct panfrost_context *ctx, const struct pipe
 
         if (!info->has_user_indices) {
                 /* Only resources can be directly mapped */
-                return rsrc->bo->gpu[0] + offset;
+                return rsrc->bo->gpu + offset;
         } else {
                 /* Otherwise, we need to upload to transient memory */
                 const uint8_t *ibuf8 = panfrost_get_index_buffer_raw(info);
@@ -1662,8 +1643,8 @@ panfrost_create_sampler_state(
                         cso->border_color.f[2],
                         cso->border_color.f[3]
                 },
-                .min_lod = FIXED_16(0.0),
-                .max_lod = FIXED_16(31.0),
+                .min_lod = FIXED_16(cso->min_lod),
+                .max_lod = FIXED_16(cso->max_lod),
                 .unknown2 = 1,
         };
 
@@ -1856,7 +1837,7 @@ panfrost_set_constant_buffer(
         struct panfrost_resource *rsrc = (struct panfrost_resource *) (buf->buffer);
 
         if (rsrc) {
-                cpu = rsrc->bo->cpu[0];
+                cpu = rsrc->bo->cpu;
         } else if (buf->user_buffer) {
                 cpu = buf->user_buffer;
         } else {
@@ -1963,7 +1944,11 @@ panfrost_create_sampler_view(
         /* TODO: Other base levels require adjusting dimensions / level numbers / etc */
         assert (template->u.tex.first_level == 0);
 
-        texture_descriptor.nr_mipmap_levels = template->u.tex.last_level - template->u.tex.first_level;
+        /* Disable mipmapping for now to avoid regressions while automipmapping
+         * is being implemented. TODO: Remove me once automipmaps work */
+
+        //texture_descriptor.nr_mipmap_levels = template->u.tex.last_level - template->u.tex.first_level;
+        texture_descriptor.nr_mipmap_levels = 0;
 
         so->hw = texture_descriptor;
 
diff --git a/src/gallium/drivers/panfrost/pan_drm.c b/src/gallium/drivers/panfrost/pan_drm.c
index bc2007e6cce..f4580da9f50 100644
--- a/src/gallium/drivers/panfrost/pan_drm.c
+++ b/src/gallium/drivers/panfrost/pan_drm.c
@@ -136,7 +136,7 @@ panfrost_drm_import_bo(struct panfrost_screen *screen, struct winsys_handle *wha
         assert(!ret);
 
 	bo->gem_handle = gem_handle;
-        bo->gpu[0] = (mali_ptr) get_bo_offset.offset;
+        bo->gpu = (mali_ptr) get_bo_offset.offset;
 
 	// TODO map and unmap on demand?
 	mmap_bo.handle = gem_handle;
@@ -146,17 +146,17 @@ panfrost_drm_import_bo(struct panfrost_screen *screen, struct winsys_handle *wha
 		assert(0);
 	}
 
-        bo->size[0] = lseek(whandle->handle, 0, SEEK_END);
-        assert(bo->size[0] > 0);
-        bo->cpu[0] = mmap(NULL, bo->size[0], PROT_READ | PROT_WRITE, MAP_SHARED,
+        bo->size = lseek(whandle->handle, 0, SEEK_END);
+        assert(bo->size > 0);
+        bo->cpu = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
                        drm->fd, mmap_bo.offset);
-        if (bo->cpu[0] == MAP_FAILED) {
-                fprintf(stderr, "mmap failed: %p\n", bo->cpu[0]);
+        if (bo->cpu == MAP_FAILED) {
+                fprintf(stderr, "mmap failed: %p\n", bo->cpu);
 		assert(0);
 	}
 
         /* Record the mmap if we're tracing */
-        pantrace_mmap(bo->gpu[0], bo->cpu[0], bo->size[0], NULL);
+        pantrace_mmap(bo->gpu, bo->cpu, bo->size, NULL);
 
         return bo;
 }
@@ -196,7 +196,7 @@ panfrost_drm_free_imported_bo(struct panfrost_screen *screen, struct panfrost_bo
 	}
 
 	bo->gem_handle = -1;
-	bo->gpu[0] = (mali_ptr)NULL;
+	bo->gpu = (mali_ptr)NULL;
 }
 
 static int
diff --git a/src/gallium/drivers/panfrost/pan_mfbd.c b/src/gallium/drivers/panfrost/pan_mfbd.c
index 6a7cd596744..25286c32da5 100644
--- a/src/gallium/drivers/panfrost/pan_mfbd.c
+++ b/src/gallium/drivers/panfrost/pan_mfbd.c
@@ -81,14 +81,14 @@ panfrost_mfbd_set_cbuf(
                 bool flip_y)
 {
         struct panfrost_resource *rsrc = pan_resource(surf->texture);
-        int stride = rsrc->bo->stride;
+        int stride = rsrc->bo->slices[0].stride;
 
         rt->format = panfrost_mfbd_format(surf);
 
         /* Now, we set the layout specific pieces */
 
         if (rsrc->bo->layout == PAN_LINEAR) {
-                mali_ptr framebuffer = rsrc->bo->gpu[0];
+                mali_ptr framebuffer = rsrc->bo->gpu;
 
                 if (flip_y) {
                         framebuffer += stride * (surf->texture->height0 - 1);
@@ -145,8 +145,8 @@ panfrost_mfbd_set_zsbuf(
                 fb->unk3 |= MALI_MFBD_EXTRA;
                 fbx->flags |= MALI_EXTRA_PRESENT | MALI_EXTRA_ZS | 0x1;
 
-                fbx->ds_linear.depth = rsrc->bo->gpu[0];
-                fbx->ds_linear.depth_stride = rsrc->bo->stride;
+                fbx->ds_linear.depth = rsrc->bo->gpu;
+                fbx->ds_linear.depth_stride = rsrc->bo->slices[0].stride;
         } else {
                 assert(0);
         }
@@ -273,7 +273,7 @@ panfrost_mfbd_fragment(struct panfrost_context *ctx, bool flip_y)
                         fb.unk3 |= MALI_MFBD_EXTRA;
                         fbx.flags |= MALI_EXTRA_PRESENT;
                         fbx.checksum_stride = rsrc->bo->checksum_stride;
-                        fbx.checksum = rsrc->bo->gpu[0] + rsrc->bo->stride * rsrc->base.height0;
+                        fbx.checksum = rsrc->bo->gpu + rsrc->bo->slices[0].stride * rsrc->base.height0;
                 }
         }
 
diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c
index 6fe871594ea..9e663e51422 100644
--- a/src/gallium/drivers/panfrost/pan_resource.c
+++ b/src/gallium/drivers/panfrost/pan_resource.c
@@ -68,7 +68,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
         prsc->screen = pscreen;
 
 	rsc->bo = screen->driver->import_bo(screen, whandle);
-	rsc->bo->stride = whandle->stride;
+	rsc->bo->slices[0].stride = whandle->stride;
 
 	if (screen->ro) {
 		rsc->scanout =
@@ -99,7 +99,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
 			return TRUE;
 
 		handle->handle = rsrc->bo->gem_handle;
-		handle->stride = rsrc->bo->stride;
+		handle->stride = rsrc->bo->slices[0].stride;
 		return TRUE;
 	} else if (handle->type == WINSYS_HANDLE_TYPE_FD) {
                 if (scanout) {
@@ -117,7 +117,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
 
                         return TRUE;
                 } else
-			return screen->driver->export_bo(screen, rsrc->bo->gem_handle, rsrc->bo->stride, handle);
+			return screen->driver->export_bo(screen, rsrc->bo->gem_handle, rsrc->bo->slices[0].stride, handle);
 	}
 
 	return FALSE;
@@ -133,8 +133,12 @@ static void
 panfrost_blit(struct pipe_context *pipe,
               const struct pipe_blit_info *info)
 {
-        /* STUB */
-        DBG("Skipping blit XXX\n");
+        if (util_try_blit_via_copy_region(pipe, info))
+                return;
+
+        /* TODO */
+        DBG("Unhandled blit.\n");
+
         return;
 }
 
@@ -183,24 +187,44 @@ panfrost_surface_destroy(struct pipe_context *pipe,
         free(surf);
 }
 
-static struct panfrost_bo *
-panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *template)
+static void
+panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo)
 {
-	struct panfrost_bo *bo = CALLOC_STRUCT(panfrost_bo);
+        unsigned width = tmpl->width0;
+        unsigned height = tmpl->height0;
+        unsigned bytes_per_pixel = util_format_get_blocksize(tmpl->format);
 
-        /* Calculate the size of the bo */
+        unsigned offset = 0;
 
-        int bytes_per_pixel = util_format_get_blocksize(template->format);
-        int stride = ALIGN(template->width0, 16) * bytes_per_pixel;
-        size_t sz = stride;
+        for (unsigned l = 0; l <= tmpl->last_level; ++l) {
+                struct panfrost_slice *slice = &bo->slices[l];
 
-        if (template->height0) sz *= template->height0;
-        if (template->depth0) sz *= template->depth0;
+                unsigned effective_width = width;
+                unsigned effective_height = height;
 
-        /* Depth buffers require extra space for unknown reasons */
+                /* Tiled operates blockwise; linear is packed */
 
-        if (template->bind & PIPE_BIND_DEPTH_STENCIL)
-                sz = sz + sz/256;
+                if (bo->layout == PAN_TILED) {
+                        effective_width = ALIGN(effective_width, 16);
+                        effective_height = ALIGN(effective_height, 16);
+                }
+
+                slice->offset = offset;
+                slice->stride = bytes_per_pixel * effective_width;
+
+                offset += slice->stride * effective_height;
+
+                width = u_minify(width, 1);
+                height = u_minify(height, 1);
+        }
+
+        bo->size = ALIGN(offset, 4096);
+}
+
+static struct panfrost_bo *
+panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *template)
+{
+	struct panfrost_bo *bo = CALLOC_STRUCT(panfrost_bo);
 
         /* Based on the usage, figure out what storing will be used. There are
          * various tradeoffs:
@@ -229,31 +253,18 @@ panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *t
         /* Set the layout appropriately */
         bo->layout = should_tile ? PAN_TILED : PAN_LINEAR;
 
-        if (bo->layout == PAN_TILED) {
-                /* For tiled, we don't map directly, so just malloc any old buffer */
-
-                for (int l = 0; l < (template->last_level + 1); ++l) {
-                        bo->cpu[l] = malloc(sz);
-                        bo->size[l] = sz;
-                }
-        } else {
-                /* For a linear resource, allocate a block of memory from
-                 * kernel space */
+        panfrost_setup_slices(template, bo);
 
+        if (bo->layout == PAN_TILED || bo->layout == PAN_LINEAR) {
                 struct panfrost_memory mem;
 
-                bo->size[0] = ALIGN(sz, 4096);
-                screen->driver->allocate_slab(screen, &mem, bo->size[0] / 4096, true, 0, 0, 0);
+                screen->driver->allocate_slab(screen, &mem, bo->size / 4096, true, 0, 0, 0);
 
-                bo->cpu[0] = mem.cpu;
-                bo->gpu[0] = mem.gpu;
+                bo->cpu = mem.cpu;
+                bo->gpu = mem.gpu;
                 bo->gem_handle = mem.gem_handle;
-
-                /* TODO: Mipmap */
         }
 
-        bo->stride = stride;
-
         return bo;
 }
 
@@ -317,27 +328,18 @@ panfrost_destroy_bo(struct panfrost_screen *screen, struct panfrost_bo *pbo)
 {
 	struct panfrost_bo *bo = (struct panfrost_bo *)pbo;
 
-        if (bo->layout == PAN_LINEAR && !bo->imported) {
-                /* Construct a memory object for all mip levels */
-
+        if ((bo->layout == PAN_LINEAR || bo->layout == PAN_TILED) &&
+                        !bo->imported) {
                 struct panfrost_memory mem = {
-                        .cpu = bo->cpu[0],
-                        .gpu = bo->gpu[0],
-                        .size = bo->size[0],
+                        .cpu = bo->cpu,
+                        .gpu = bo->gpu,
+                        .size = bo->size,
                         .gem_handle = bo->gem_handle,
                 };
 
                 screen->driver->free_slab(screen, &mem);
         }
 
-        if (bo->layout == PAN_TILED) {
-                /* Tiled has a malloc'd CPU, so just plain ol' free needed */
-
-                for (int l = 0; l < MAX_MIP_LEVELS; ++l) {
-                        free(bo->cpu[l]);
-                }
-        }
-
         if (bo->layout == PAN_AFBC) {
                 /* TODO */
                 DBG("--leaking afbc (%d bytes)--\n", bo->afbc_metadata_size);
@@ -369,30 +371,6 @@ panfrost_resource_destroy(struct pipe_screen *screen,
 	FREE(rsrc);
 }
 
-static uint8_t *
-panfrost_map_bo(struct panfrost_context *ctx, struct pipe_transfer *transfer)
-{
-	struct panfrost_bo *bo = (struct panfrost_bo *)pan_resource(transfer->resource)->bo;
-
-        /* If non-zero level, it's a mipmapped resource and needs to be treated as such */
-        bo->is_mipmap |= transfer->level;
-
-        if (transfer->usage & PIPE_TRANSFER_MAP_DIRECTLY && bo->layout != PAN_LINEAR) {
-                /* We can only directly map linear resources */
-                return NULL;
-        }
-
-        if (transfer->resource->bind & PIPE_BIND_DEPTH_STENCIL) {
-                /* Mipmapped readpixels?! */
-                assert(transfer->level == 0);
-
-                /* Set the CPU mapping to that of the depth/stencil buffer in memory, untiled */
-                bo->cpu[transfer->level] = ctx->depth_stencil_buffer.cpu;
-        }
-
-        return bo->cpu[transfer->level];
-}
-
 static void *
 panfrost_transfer_map(struct pipe_context *pctx,
                       struct pipe_resource *resource,
@@ -401,21 +379,20 @@ panfrost_transfer_map(struct pipe_context *pctx,
                       const struct pipe_box *box,
                       struct pipe_transfer **out_transfer)
 {
-        struct panfrost_context *ctx = pan_context(pctx);
         int bytes_per_pixel = util_format_get_blocksize(resource->format);
         struct panfrost_bo *bo = pan_resource(resource)->bo;
-	uint8_t *cpu;
 
-        struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
-        transfer->level = level;
-        transfer->usage = usage;
-        transfer->box = *box;
-        transfer->stride = bo->stride;
-        assert(!transfer->box.z);
+        struct panfrost_gtransfer *transfer = CALLOC_STRUCT(panfrost_gtransfer);
+        transfer->base.level = level;
+        transfer->base.usage = usage;
+        transfer->base.box = *box;
+        transfer->base.stride = bo->slices[level].stride;
+        transfer->base.layer_stride = bytes_per_pixel * resource->width0; /* TODO: Cubemaps */
+        assert(!transfer->base.box.z);
 
-        pipe_resource_reference(&transfer->resource, resource);
+        pipe_resource_reference(&transfer->base.resource, resource);
 
-        *out_transfer = transfer;
+        *out_transfer = &transfer->base;
 
         if (resource->bind & PIPE_BIND_DISPLAY_TARGET ||
             resource->bind & PIPE_BIND_SCANOUT ||
@@ -427,54 +404,49 @@ panfrost_transfer_map(struct pipe_context *pctx,
                 panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME);
         }
 
-	cpu = panfrost_map_bo(ctx, transfer);
-	if (cpu == NULL)
-		return NULL;
+        if (bo->layout != PAN_LINEAR) {
+                /* Non-linear resources need to be indirectly mapped */
 
-        return cpu + transfer->box.x * bytes_per_pixel + transfer->box.y * bo->stride;
+                if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
+                        return NULL;
+
+                /* TODO: Reads */
+                transfer->map = malloc(ALIGN(box->width, 16) * ALIGN(box->height, 16) * bytes_per_pixel);
+
+                return transfer->map;
+        } else {
+                return bo->cpu
+                        + bo->slices[level].offset
+                        + transfer->base.box.y * bo->slices[level].stride
+                        + transfer->base.box.x * bytes_per_pixel;
+        }
 }
 
 static void
-panfrost_tile_texture(struct panfrost_screen *screen, struct panfrost_resource *rsrc, int level)
+panfrost_tile_texture(struct panfrost_screen *screen, struct panfrost_resource *rsrc, struct panfrost_gtransfer *trans)
 {
 	struct panfrost_bo *bo = (struct panfrost_bo *)rsrc->bo;
-        int bytes_per_pixel = util_format_get_blocksize(rsrc->base.format);
-
-        int width = rsrc->base.width0 >> level;
-        int height = rsrc->base.height0 >> level;
-
-        /* Estimate swizzled bitmap size. Slight overestimates are fine.
-         * Underestimates will result in memory corruption or worse. */
 
-        int swizzled_sz = panfrost_swizzled_size(width, height, bytes_per_pixel);
+        unsigned level = trans->base.level;
 
-        /* Save the entry. But if there was already an entry here (from a
-         * previous upload of the resource), free that one so we don't leak */
+        assert(!trans->base.box.z);
 
-        if (bo->entry[level] != NULL) {
-                bo->entry[level]->freed = true;
-                pb_slab_free(&screen->slabs, &bo->entry[level]->base);
-        }
-
-        /* Allocate the transfer given that known size but do not copy */
-        struct pb_slab_entry *entry = pb_slab_alloc(&screen->slabs, swizzled_sz, HEAP_TEXTURE);
-        struct panfrost_memory_entry *p_entry = (struct panfrost_memory_entry *) entry;
-        struct panfrost_memory *backing = (struct panfrost_memory *) entry->slab;
-        uint8_t *swizzled = backing->cpu + p_entry->offset;
-
-        bo->entry[level] = p_entry;
-        bo->gpu[level] = backing->gpu + p_entry->offset;
-
-        /* Run actual texture swizzle, writing directly to the mapped
-         * GPU chunk we allocated */
-
-        panfrost_texture_swizzle(width, height, bytes_per_pixel, bo->stride, bo->cpu[level], swizzled);
+        panfrost_texture_swizzle(
+                        trans->base.box.x,
+                        trans->base.box.y,
+                        trans->base.box.width,
+                        trans->base.box.height,
+                        util_format_get_blocksize(rsrc->base.format),
+                        bo->slices[level].stride,
+                        trans->map,
+                        bo->cpu + bo->slices[level].offset);
 }
 
 static void
 panfrost_unmap_bo(struct panfrost_context *ctx,
                          struct pipe_transfer *transfer)
 {
+        struct panfrost_gtransfer *trans = pan_transfer(transfer);
 	struct panfrost_bo *bo = (struct panfrost_bo *)pan_resource(transfer->resource)->bo;
 
         if (transfer->usage & PIPE_TRANSFER_WRITE) {
@@ -487,10 +459,12 @@ panfrost_unmap_bo(struct panfrost_context *ctx,
                         } else if (bo->layout == PAN_TILED) {
                                 struct pipe_context *gallium = (struct pipe_context *) ctx;
                                 struct panfrost_screen *screen = pan_screen(gallium->screen);
-                                panfrost_tile_texture(screen, prsrc, transfer->level);
+                                panfrost_tile_texture(screen, prsrc, trans);
                         }
                 }
         }
+
+        free(trans->map);
 }
 
 static void
@@ -628,7 +602,6 @@ panfrost_resource_context_init(struct pipe_context *pctx)
         pctx->surface_destroy = panfrost_surface_destroy;
         pctx->resource_copy_region = util_resource_copy_region;
         pctx->blit = panfrost_blit;
-        //pctx->generate_mipmap = panfrost_generate_mipmap;
         pctx->flush_resource = panfrost_flush_resource;
         pctx->invalidate_resource = panfrost_invalidate_resource;
         pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region;
diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h
index 4b5b9c49c07..3e076b873f7 100644
--- a/src/gallium/drivers/panfrost/pan_resource.h
+++ b/src/gallium/drivers/panfrost/pan_resource.h
@@ -39,32 +39,29 @@ enum panfrost_memory_layout {
         PAN_AFBC
 };
 
-struct panfrost_bo {
-        /* Address to the BO in question */
+struct panfrost_slice {
+        unsigned offset;
+        unsigned stride;
+};
 
-        uint8_t *cpu[MAX_MIP_LEVELS];
+struct panfrost_bo {
+        struct panfrost_slice slices[MAX_MIP_LEVELS];
 
-        /* Not necessarily a GPU mapping of cpu! In case of texture tiling, gpu
-         * points to the GPU-side, tiled texture, while cpu points to the
-         * CPU-side, untiled texture from mesa */
+        /* Mapping for the entire object (all levels) */
+        uint8_t *cpu;
 
-        mali_ptr gpu[MAX_MIP_LEVELS];
+        /* GPU address for the object */
+        mali_ptr gpu;
 
-        /* Memory entry corresponding to gpu above */
-        struct panfrost_memory_entry *entry[MAX_MIP_LEVELS];
+        /* Size of the entire tree */
+        size_t size;
 
         /* Set if this bo was imported rather than allocated */
         bool imported;
 
-        /* Number of bytes of allocation */
-        size_t size[MAX_MIP_LEVELS];
-
         /* Internal layout (tiled?) */
         enum panfrost_memory_layout layout;
 
-        /* Is something other than level 0 ever written? */
-        bool is_mipmap;
-
         /* If AFBC is enabled for this resource, we lug around an AFBC
          * metadata buffer as well. The actual AFBC resource is also in
          * afbc_slab (only defined for AFBC) at position afbc_main_offset
@@ -81,7 +78,6 @@ struct panfrost_bo {
         int checksum_stride;
 
         int gem_handle;
-        unsigned int stride;
 };
 
 struct panfrost_resource {
@@ -99,6 +95,17 @@ pan_resource(struct pipe_resource *p)
    return (struct panfrost_resource *)p;
 }
 
+struct panfrost_gtransfer {
+        struct pipe_transfer base;
+        void *map;
+};
+
+static inline struct panfrost_gtransfer *
+pan_transfer(struct pipe_transfer *p)
+{
+   return (struct panfrost_gtransfer *)p;
+}
+
 void panfrost_resource_screen_init(struct panfrost_screen *screen);
 
 void panfrost_resource_context_init(struct pipe_context *pctx);
diff --git a/src/gallium/drivers/panfrost/pan_sfbd.c b/src/gallium/drivers/panfrost/pan_sfbd.c
index 787fef2c16e..4235c198199 100644
--- a/src/gallium/drivers/panfrost/pan_sfbd.c
+++ b/src/gallium/drivers/panfrost/pan_sfbd.c
@@ -92,12 +92,12 @@ panfrost_sfbd_set_cbuf(
 {
         struct panfrost_resource *rsrc = pan_resource(surf->texture);
 
-        signed stride = rsrc->bo->stride;
+        signed stride = rsrc->bo->slices[0].stride;
 
         fb->format = panfrost_sfbd_format(surf);
 
         if (rsrc->bo->layout == PAN_LINEAR) {
-                mali_ptr framebuffer = rsrc->bo->gpu[0];
+                mali_ptr framebuffer = rsrc->bo->gpu;
 
                 /* The default is upside down from OpenGL's perspective. */
                 if (flip_y) {
diff --git a/src/gallium/drivers/panfrost/pan_swizzle.c b/src/gallium/drivers/panfrost/pan_swizzle.c
index 0fe8b3cfa21..578de655415 100644
--- a/src/gallium/drivers/panfrost/pan_swizzle.c
+++ b/src/gallium/drivers/panfrost/pan_swizzle.c
@@ -147,7 +147,9 @@ swizzle_bpp4_align16(int width, int height, int source_stride, int block_pitch,
 }
 
 void
-panfrost_texture_swizzle(int width, int height, int bytes_per_pixel, int source_stride,
+panfrost_texture_swizzle(unsigned off_x,
+                         unsigned off_y,
+                         int width, int height, int bytes_per_pixel, int source_stride,
                          const uint8_t *pixels,
                          uint8_t *ldest)
 {
@@ -155,25 +157,27 @@ panfrost_texture_swizzle(int width, int height, int bytes_per_pixel, int source_
         int block_pitch = ALIGN(width, 16) >> 4;
 
         /* Use fast path if available */
-        if (bytes_per_pixel == 4 /* && (ALIGN(width, 16) == width) */) {
-                swizzle_bpp4_align16(width, height, source_stride >> 2, (block_pitch * 256 >> 4), (const uint32_t *) pixels, (uint32_t *) ldest);
-                return;
-        } else if (bytes_per_pixel == 1 /* && (ALIGN(width, 16) == width) */) {
-                swizzle_bpp1_align16(width, height, source_stride, (block_pitch * 256 >> 4), pixels, (uint8_t *) ldest);
-                return;
+        if (!(off_x || off_y)) {
+                if (bytes_per_pixel == 4 /* && (ALIGN(width, 16) == width) */) {
+                        swizzle_bpp4_align16(width, height, source_stride >> 2, (block_pitch * 256 >> 4), (const uint32_t *) pixels, (uint32_t *) ldest);
+                        return;
+                } else if (bytes_per_pixel == 1 /* && (ALIGN(width, 16) == width) */) {
+                        swizzle_bpp1_align16(width, height, source_stride, (block_pitch * 256 >> 4), pixels, (uint8_t *) ldest);
+                        return;
+                }
         }
 
         /* Otherwise, default back on generic path */
 
         for (int y = 0; y < height; ++y) {
-                int block_y = y >> 4;
-                int rem_y = y & 0x0F;
+                int block_y = (y + off_y) >> 4;
+                int rem_y = (y + off_y) & 0x0F;
                 int block_start_s = block_y * block_pitch * 256;
                 int source_start = y * source_stride;
 
                 for (int x = 0; x < width; ++x) {
-                        int block_x_s = (x >> 4) * 256;
-                        int rem_x = x & 0x0F;
+                        int block_x_s = ((x + off_x) >> 4) * 256;
+                        int rem_x = (x + off_x) & 0x0F;
 
                         int index = space_filler[rem_y][rem_x];
                         const uint8_t *source = &pixels[source_start + bytes_per_pixel * x];
@@ -184,14 +188,3 @@ panfrost_texture_swizzle(int width, int height, int bytes_per_pixel, int source_
                 }
         }
 }
-
-
-unsigned
-panfrost_swizzled_size(int width, int height, int bytes_per_pixel)
-{
-        /* Calculate maximum size, overestimating a bit */
-        int block_pitch = ALIGN(width, 16) >> 4;
-        unsigned sz = bytes_per_pixel * 256 * ((height >> 4) + 1) * block_pitch;
-
-        return sz;
-}
diff --git a/src/gallium/drivers/panfrost/pan_swizzle.h b/src/gallium/drivers/panfrost/pan_swizzle.h
index d375cfe53a5..a4d603a0aad 100644
--- a/src/gallium/drivers/panfrost/pan_swizzle.h
+++ b/src/gallium/drivers/panfrost/pan_swizzle.h
@@ -31,11 +31,9 @@ void
 panfrost_generate_space_filler_indices(void);
 
 void
-panfrost_texture_swizzle(int width, int height, int bytes_per_pixel, int source_stride,
+panfrost_texture_swizzle(unsigned off_x, unsigned off_y,
+                        int width, int height, int bytes_per_pixel, int source_stride,
                          const uint8_t *pixels,
                          uint8_t *ldest);
 
-unsigned
-panfrost_swizzled_size(int width, int height, int bytes_per_pixel);
-
 #endif
-- 
2.20.1



More information about the mesa-dev mailing list