summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/freedreno_resource.c
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2014-12-12 13:38:05 -0500
committerRob Clark <[email protected]>2014-12-13 15:09:37 -0500
commit0ebd623f6058fd20ee28e206da2da259073fdf86 (patch)
tree437f4a57e9307a265575b79aabb9cda333df8c92 /src/gallium/drivers/freedreno/freedreno_resource.c
parentcf80694df5fada3d2197626e5a878f17b67625f9 (diff)
freedreno/a4xx: mipmaps
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_resource.c')
-rw-r--r--src/gallium/drivers/freedreno/freedreno_resource.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c
index d604aa3f1f8..c412407314f 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -101,6 +101,7 @@ fd_resource_transfer_map(struct pipe_context *pctx,
struct pipe_transfer *ptrans;
enum pipe_format format = prsc->format;
uint32_t op = 0;
+ uint32_t offset;
char *buf;
int ret = 0;
@@ -146,10 +147,19 @@ fd_resource_transfer_map(struct pipe_context *pctx,
*pptrans = ptrans;
- return buf + slice->offset +
- box->y / util_format_get_blockheight(format) * ptrans->stride +
- box->x / util_format_get_blockwidth(format) * rsc->cpp +
- box->z * slice->size0;
+ if (rsc->layer_first) {
+ offset = slice->offset +
+ box->y / util_format_get_blockheight(format) * ptrans->stride +
+ box->x / util_format_get_blockwidth(format) * rsc->cpp +
+ box->z * rsc->layer_size;
+ } else {
+ offset = slice->offset +
+ box->y / util_format_get_blockheight(format) * ptrans->stride +
+ box->x / util_format_get_blockwidth(format) * rsc->cpp +
+ box->z * slice->size0;
+ }
+
+ return buf + offset;
fail:
fd_resource_transfer_unmap(pctx, ptrans);
@@ -195,6 +205,10 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
uint32_t width = prsc->width0;
uint32_t height = prsc->height0;
uint32_t depth = prsc->depth0;
+ /* in layer_first layout, the level (slice) contains just one
+ * layer (since in fact the layer contains the slices)
+ */
+ uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size;
for (level = 0; level <= prsc->last_level; level++) {
struct fd_resource_slice *slice = fd_resource_slice(rsc, level);
@@ -203,7 +217,7 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
slice->offset = size;
slice->size0 = align(slice->pitch * height * rsc->cpp, alignment);
- size += slice->size0 * depth * prsc->array_size;
+ size += slice->size0 * depth * layers_in_level;
width = u_minify(width, 1);
height = u_minify(height, 1);
@@ -216,12 +230,6 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment)
static uint32_t
slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl)
{
- struct fd_screen *screen = fd_screen(pscreen);
-
- /* on a4xx, seems like everything is aligned to page: */
- if ((screen->gpu_id >= 400) && (screen->gpu_id < 500))
- return 4096;
-
/* on a3xx, 2d array and 3d textures seem to want their
* layers aligned to page boundaries:
*/
@@ -266,8 +274,25 @@ fd_resource_create(struct pipe_screen *pscreen,
assert(rsc->cpp);
+ if (is_a4xx(fd_screen(pscreen))) {
+ switch (tmpl->target) {
+ case PIPE_TEXTURE_3D:
+ /* TODO 3D_ARRAY? */
+ rsc->layer_first = false;
+ break;
+ default:
+ rsc->layer_first = true;
+ break;
+ }
+ }
+
size = setup_slices(rsc, slice_alignment(pscreen, tmpl));
+ if (rsc->layer_first) {
+ rsc->layer_size = align(size, 4096);
+ size = rsc->layer_size * prsc->array_size;
+ }
+
realloc_bo(rsc, size);
if (!rsc->bo)
goto fail;