diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/freedreno_resource.c')
-rw-r--r-- | src/gallium/drivers/freedreno/freedreno_resource.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c new file mode 100644 index 00000000000..4458ba99557 --- /dev/null +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -0,0 +1,248 @@ +/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ + +/* + * Copyright (C) 2012 Rob Clark <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Rob Clark <[email protected]> + */ + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_transfer.h" +#include "util/u_string.h" + +#include "freedreno_resource.h" +#include "freedreno_screen.h" +#include "freedreno_surface.h" +#include "freedreno_context.h" +#include "freedreno_util.h" + +static void * +fd_resource_transfer_map(struct pipe_context *pctx, + struct pipe_resource *prsc, + unsigned level, unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **pptrans) +{ + struct fd_context *ctx = fd_context(pctx); + struct fd_resource *rsc = fd_resource(prsc); + struct pipe_transfer *ptrans = util_slab_alloc(&ctx->transfer_pool); + enum pipe_format format = prsc->format; + char *buf; + + if (!ptrans) + return NULL; + + ptrans->resource = prsc; + ptrans->level = level; + ptrans->usage = usage; + ptrans->box = *box; + ptrans->stride = rsc->pitch * rsc->cpp; + ptrans->layer_stride = ptrans->stride; + + buf = fd_bo_map(rsc->bo); + + *pptrans = ptrans; + + return buf + + box->y / util_format_get_blockheight(format) * ptrans->stride + + box->x / util_format_get_blockwidth(format) * rsc->cpp; +} + +static void fd_resource_transfer_flush_region(struct pipe_context *pctx, + struct pipe_transfer *ptrans, + const struct pipe_box *box) +{ + struct fd_context *ctx = fd_context(pctx); + struct fd_resource *rsc = fd_resource(ptrans->resource); + + if (rsc->dirty) + fd_context_render(pctx); + + if (rsc->timestamp) { + fd_pipe_wait(ctx->screen->pipe, rsc->timestamp); + rsc->timestamp = 0; + } +} + +static void +fd_resource_transfer_unmap(struct pipe_context *pctx, + struct pipe_transfer *ptrans) +{ + struct fd_context *ctx = fd_context(pctx); + util_slab_free(&ctx->transfer_pool, ptrans); +} + +static void +fd_resource_destroy(struct pipe_screen *pscreen, + struct pipe_resource *prsc) +{ + struct fd_resource *rsc = fd_resource(prsc); + fd_bo_del(rsc->bo); + FREE(rsc); +} + +static boolean +fd_resource_get_handle(struct pipe_screen *pscreen, + struct pipe_resource *prsc, + struct winsys_handle *handle) +{ + struct fd_resource *rsc = fd_resource(prsc); + + return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->pitch, handle); +} + + +const struct u_resource_vtbl fd_resource_vtbl = { + .resource_get_handle = fd_resource_get_handle, + .resource_destroy = fd_resource_destroy, + .transfer_map = fd_resource_transfer_map, + .transfer_flush_region = fd_resource_transfer_flush_region, + .transfer_unmap = fd_resource_transfer_unmap, + .transfer_inline_write = u_default_transfer_inline_write, +}; + +/** + * Create a new texture object, using the given template info. + */ +static struct pipe_resource * +fd_resource_create(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl) +{ + struct fd_screen *screen = fd_screen(pscreen); + struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); + struct pipe_resource *prsc = &rsc->base.b; + uint32_t flags, size; + + DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, " + "nr_samples=%u, usage=%u, bind=%x, flags=%x", + tmpl->target, util_format_name(tmpl->format), + tmpl->width0, tmpl->height0, tmpl->depth0, + tmpl->array_size, tmpl->last_level, tmpl->nr_samples, + tmpl->usage, tmpl->bind, tmpl->flags); + + if (!rsc) + return NULL; + + *prsc = *tmpl; + + pipe_reference_init(&prsc->reference, 1); + prsc->screen = pscreen; + + rsc->base.vtbl = &fd_resource_vtbl; + rsc->pitch = ALIGN(tmpl->width0, 32); + rsc->cpp = util_format_get_blocksize(tmpl->format); + + size = rsc->pitch * tmpl->height0 * rsc->cpp; + flags = DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */ + + rsc->bo = fd_bo_new(screen->dev, size, flags); + + return prsc; +} + +/** + * Create a texture from a winsys_handle. The handle is often created in + * another process by first creating a pipe texture and then calling + * resource_get_handle. + */ +static struct pipe_resource * +fd_resource_from_handle(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl, + struct winsys_handle *handle) +{ + struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); + struct pipe_resource *prsc = &rsc->base.b; + + DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, " + "nr_samples=%u, usage=%u, bind=%x, flags=%x", + tmpl->target, util_format_name(tmpl->format), + tmpl->width0, tmpl->height0, tmpl->depth0, + tmpl->array_size, tmpl->last_level, tmpl->nr_samples, + tmpl->usage, tmpl->bind, tmpl->flags); + + if (!rsc) + return NULL; + + *prsc = *tmpl; + + pipe_reference_init(&prsc->reference, 1); + prsc->screen = pscreen; + + rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &rsc->pitch); + + rsc->base.vtbl = &fd_resource_vtbl; + rsc->pitch = ALIGN(tmpl->width0, 32); + + return prsc; +} + +/** + * Copy a block of pixels from one resource to another. + * The resource must be of the same format. + * Resources with nr_samples > 1 are not allowed. + */ +static void +fd_resource_copy_region(struct pipe_context *pctx, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) +{ + DBG("TODO: "); + // TODO +} + +/* Optimal hardware path for blitting pixels. + * Scaling, format conversion, up- and downsampling (resolve) are allowed. + */ +static void +fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) +{ + DBG("TODO: "); + // TODO +} + +void +fd_resource_screen_init(struct pipe_screen *pscreen) +{ + pscreen->resource_create = fd_resource_create; + pscreen->resource_from_handle = fd_resource_from_handle; + pscreen->resource_get_handle = u_resource_get_handle_vtbl; + pscreen->resource_destroy = u_resource_destroy_vtbl; +} + +void +fd_resource_context_init(struct pipe_context *pctx) +{ + pctx->transfer_map = u_transfer_map_vtbl; + pctx->transfer_flush_region = u_transfer_flush_region_vtbl; + pctx->transfer_unmap = u_transfer_unmap_vtbl; + pctx->transfer_inline_write = u_transfer_inline_write_vtbl; + pctx->create_surface = fd_create_surface; + pctx->surface_destroy = fd_surface_destroy; + pctx->resource_copy_region = fd_resource_copy_region; + pctx->blit = fd_blit; +} |