4458ba995579cf318c26432b1cfb2bb9323ff317
[mesa.git] / src / gallium / drivers / freedreno / freedreno_resource.c
1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3 /*
4 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29 #include "util/u_format.h"
30 #include "util/u_inlines.h"
31 #include "util/u_transfer.h"
32 #include "util/u_string.h"
33
34 #include "freedreno_resource.h"
35 #include "freedreno_screen.h"
36 #include "freedreno_surface.h"
37 #include "freedreno_context.h"
38 #include "freedreno_util.h"
39
40 static void *
41 fd_resource_transfer_map(struct pipe_context *pctx,
42 struct pipe_resource *prsc,
43 unsigned level, unsigned usage,
44 const struct pipe_box *box,
45 struct pipe_transfer **pptrans)
46 {
47 struct fd_context *ctx = fd_context(pctx);
48 struct fd_resource *rsc = fd_resource(prsc);
49 struct pipe_transfer *ptrans = util_slab_alloc(&ctx->transfer_pool);
50 enum pipe_format format = prsc->format;
51 char *buf;
52
53 if (!ptrans)
54 return NULL;
55
56 ptrans->resource = prsc;
57 ptrans->level = level;
58 ptrans->usage = usage;
59 ptrans->box = *box;
60 ptrans->stride = rsc->pitch * rsc->cpp;
61 ptrans->layer_stride = ptrans->stride;
62
63 buf = fd_bo_map(rsc->bo);
64
65 *pptrans = ptrans;
66
67 return buf +
68 box->y / util_format_get_blockheight(format) * ptrans->stride +
69 box->x / util_format_get_blockwidth(format) * rsc->cpp;
70 }
71
72 static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
73 struct pipe_transfer *ptrans,
74 const struct pipe_box *box)
75 {
76 struct fd_context *ctx = fd_context(pctx);
77 struct fd_resource *rsc = fd_resource(ptrans->resource);
78
79 if (rsc->dirty)
80 fd_context_render(pctx);
81
82 if (rsc->timestamp) {
83 fd_pipe_wait(ctx->screen->pipe, rsc->timestamp);
84 rsc->timestamp = 0;
85 }
86 }
87
88 static void
89 fd_resource_transfer_unmap(struct pipe_context *pctx,
90 struct pipe_transfer *ptrans)
91 {
92 struct fd_context *ctx = fd_context(pctx);
93 util_slab_free(&ctx->transfer_pool, ptrans);
94 }
95
96 static void
97 fd_resource_destroy(struct pipe_screen *pscreen,
98 struct pipe_resource *prsc)
99 {
100 struct fd_resource *rsc = fd_resource(prsc);
101 fd_bo_del(rsc->bo);
102 FREE(rsc);
103 }
104
105 static boolean
106 fd_resource_get_handle(struct pipe_screen *pscreen,
107 struct pipe_resource *prsc,
108 struct winsys_handle *handle)
109 {
110 struct fd_resource *rsc = fd_resource(prsc);
111
112 return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->pitch, handle);
113 }
114
115
116 const struct u_resource_vtbl fd_resource_vtbl = {
117 .resource_get_handle = fd_resource_get_handle,
118 .resource_destroy = fd_resource_destroy,
119 .transfer_map = fd_resource_transfer_map,
120 .transfer_flush_region = fd_resource_transfer_flush_region,
121 .transfer_unmap = fd_resource_transfer_unmap,
122 .transfer_inline_write = u_default_transfer_inline_write,
123 };
124
125 /**
126 * Create a new texture object, using the given template info.
127 */
128 static struct pipe_resource *
129 fd_resource_create(struct pipe_screen *pscreen,
130 const struct pipe_resource *tmpl)
131 {
132 struct fd_screen *screen = fd_screen(pscreen);
133 struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
134 struct pipe_resource *prsc = &rsc->base.b;
135 uint32_t flags, size;
136
137 DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, "
138 "nr_samples=%u, usage=%u, bind=%x, flags=%x",
139 tmpl->target, util_format_name(tmpl->format),
140 tmpl->width0, tmpl->height0, tmpl->depth0,
141 tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
142 tmpl->usage, tmpl->bind, tmpl->flags);
143
144 if (!rsc)
145 return NULL;
146
147 *prsc = *tmpl;
148
149 pipe_reference_init(&prsc->reference, 1);
150 prsc->screen = pscreen;
151
152 rsc->base.vtbl = &fd_resource_vtbl;
153 rsc->pitch = ALIGN(tmpl->width0, 32);
154 rsc->cpp = util_format_get_blocksize(tmpl->format);
155
156 size = rsc->pitch * tmpl->height0 * rsc->cpp;
157 flags = DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */
158
159 rsc->bo = fd_bo_new(screen->dev, size, flags);
160
161 return prsc;
162 }
163
164 /**
165 * Create a texture from a winsys_handle. The handle is often created in
166 * another process by first creating a pipe texture and then calling
167 * resource_get_handle.
168 */
169 static struct pipe_resource *
170 fd_resource_from_handle(struct pipe_screen *pscreen,
171 const struct pipe_resource *tmpl,
172 struct winsys_handle *handle)
173 {
174 struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
175 struct pipe_resource *prsc = &rsc->base.b;
176
177 DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, "
178 "nr_samples=%u, usage=%u, bind=%x, flags=%x",
179 tmpl->target, util_format_name(tmpl->format),
180 tmpl->width0, tmpl->height0, tmpl->depth0,
181 tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
182 tmpl->usage, tmpl->bind, tmpl->flags);
183
184 if (!rsc)
185 return NULL;
186
187 *prsc = *tmpl;
188
189 pipe_reference_init(&prsc->reference, 1);
190 prsc->screen = pscreen;
191
192 rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &rsc->pitch);
193
194 rsc->base.vtbl = &fd_resource_vtbl;
195 rsc->pitch = ALIGN(tmpl->width0, 32);
196
197 return prsc;
198 }
199
200 /**
201 * Copy a block of pixels from one resource to another.
202 * The resource must be of the same format.
203 * Resources with nr_samples > 1 are not allowed.
204 */
205 static void
206 fd_resource_copy_region(struct pipe_context *pctx,
207 struct pipe_resource *dst,
208 unsigned dst_level,
209 unsigned dstx, unsigned dsty, unsigned dstz,
210 struct pipe_resource *src,
211 unsigned src_level,
212 const struct pipe_box *src_box)
213 {
214 DBG("TODO: ");
215 // TODO
216 }
217
218 /* Optimal hardware path for blitting pixels.
219 * Scaling, format conversion, up- and downsampling (resolve) are allowed.
220 */
221 static void
222 fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *info)
223 {
224 DBG("TODO: ");
225 // TODO
226 }
227
228 void
229 fd_resource_screen_init(struct pipe_screen *pscreen)
230 {
231 pscreen->resource_create = fd_resource_create;
232 pscreen->resource_from_handle = fd_resource_from_handle;
233 pscreen->resource_get_handle = u_resource_get_handle_vtbl;
234 pscreen->resource_destroy = u_resource_destroy_vtbl;
235 }
236
237 void
238 fd_resource_context_init(struct pipe_context *pctx)
239 {
240 pctx->transfer_map = u_transfer_map_vtbl;
241 pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
242 pctx->transfer_unmap = u_transfer_unmap_vtbl;
243 pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
244 pctx->create_surface = fd_create_surface;
245 pctx->surface_destroy = fd_surface_destroy;
246 pctx->resource_copy_region = fd_resource_copy_region;
247 pctx->blit = fd_blit;
248 }