• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include "util/format/u_format.h"
28 #include "util/format/u_format_rgtc.h"
29 #include "util/format/u_format_zs.h"
30 #include "util/u_inlines.h"
31 #include "util/u_transfer.h"
32 #include "util/u_string.h"
33 #include "util/u_surface.h"
34 #include "util/set.h"
35 #include "util/u_drm.h"
36 
37 #include "decode/util.h"
38 
39 #include "freedreno_resource.h"
40 #include "freedreno_batch_cache.h"
41 #include "freedreno_blitter.h"
42 #include "freedreno_fence.h"
43 #include "freedreno_screen.h"
44 #include "freedreno_surface.h"
45 #include "freedreno_context.h"
46 #include "freedreno_query_hw.h"
47 #include "freedreno_util.h"
48 
49 #include "drm-uapi/drm_fourcc.h"
50 #include <errno.h>
51 
52 /* XXX this should go away, needed for 'struct winsys_handle' */
53 #include "frontend/drm_driver.h"
54 
55 /* A private modifier for now, so we have a way to request tiled but not
56  * compressed.  It would perhaps be good to get real modifiers for the
57  * tiled formats, but would probably need to do some work to figure out
58  * the layout(s) of the tiled modes, and whether they are the same
59  * across generations.
60  */
61 #define FD_FORMAT_MOD_QCOM_TILED	fourcc_mod_code(QCOM, 0xffffffff)
62 
63 /**
64  * Go through the entire state and see if the resource is bound
65  * anywhere. If it is, mark the relevant state as dirty. This is
66  * called on realloc_bo to ensure the necessary state is re-
67  * emitted so the GPU looks at the new backing bo.
68  */
69 static void
rebind_resource_in_ctx(struct fd_context * ctx,struct fd_resource * rsc)70 rebind_resource_in_ctx(struct fd_context *ctx, struct fd_resource *rsc)
71 {
72 	struct pipe_resource *prsc = &rsc->base;
73 
74 	if (ctx->rebind_resource)
75 		ctx->rebind_resource(ctx, rsc);
76 
77 	/* VBOs */
78 	if (rsc->dirty & FD_DIRTY_VTXBUF) {
79 		struct fd_vertexbuf_stateobj *vb = &ctx->vtx.vertexbuf;
80 		for (unsigned i = 0; i < vb->count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) {
81 			if (vb->vb[i].buffer.resource == prsc)
82 				ctx->dirty |= FD_DIRTY_VTXBUF;
83 		}
84 	}
85 
86 	const enum fd_dirty_3d_state per_stage_dirty =
87 			FD_DIRTY_CONST | FD_DIRTY_TEX | FD_DIRTY_IMAGE | FD_DIRTY_SSBO;
88 
89 	if (!(rsc->dirty & per_stage_dirty))
90 		return;
91 
92 	/* per-shader-stage resources: */
93 	for (unsigned stage = 0; stage < PIPE_SHADER_TYPES; stage++) {
94 		/* Constbufs.. note that constbuf[0] is normal uniforms emitted in
95 		 * cmdstream rather than by pointer..
96 		 */
97 		if ((rsc->dirty & FD_DIRTY_CONST) &&
98 				!(ctx->dirty_shader[stage] & FD_DIRTY_CONST)) {
99 			struct fd_constbuf_stateobj *cb = &ctx->constbuf[stage];
100 			const unsigned num_ubos = util_last_bit(cb->enabled_mask);
101 			for (unsigned i = 1; i < num_ubos; i++) {
102 				if (cb->cb[i].buffer == prsc) {
103 					ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_CONST;
104 					ctx->dirty |= FD_DIRTY_CONST;
105 					break;
106 				}
107 			}
108 		}
109 
110 		/* Textures */
111 		if ((rsc->dirty & FD_DIRTY_TEX) &&
112 				!(ctx->dirty_shader[stage] & FD_DIRTY_TEX)) {
113 			struct fd_texture_stateobj *tex = &ctx->tex[stage];
114 			for (unsigned i = 0; i < tex->num_textures; i++) {
115 				if (tex->textures[i] && (tex->textures[i]->texture == prsc)) {
116 					ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_TEX;
117 					ctx->dirty |= FD_DIRTY_TEX;
118 					break;
119 				}
120 			}
121 		}
122 
123 		/* Images */
124 		if ((rsc->dirty & FD_DIRTY_IMAGE) &&
125 				!(ctx->dirty_shader[stage] & FD_DIRTY_IMAGE)) {
126 			struct fd_shaderimg_stateobj *si = &ctx->shaderimg[stage];
127 			const unsigned num_images = util_last_bit(si->enabled_mask);
128 			for (unsigned i = 0; i < num_images; i++) {
129 				if (si->si[i].resource == prsc) {
130 					ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_IMAGE;
131 					ctx->dirty |= FD_DIRTY_IMAGE;
132 					break;
133 				}
134 			}
135 		}
136 
137 		/* SSBOs */
138 		if ((rsc->dirty & FD_DIRTY_SSBO) &&
139 				!(ctx->dirty_shader[stage] & FD_DIRTY_SSBO)) {
140 			struct fd_shaderbuf_stateobj *sb = &ctx->shaderbuf[stage];
141 			const unsigned num_ssbos = util_last_bit(sb->enabled_mask);
142 			for (unsigned i = 0; i < num_ssbos; i++) {
143 				if (sb->sb[i].buffer == prsc) {
144 					ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_SSBO;
145 					ctx->dirty |= FD_DIRTY_SSBO;
146 					break;
147 				}
148 			}
149 		}
150 	}
151 }
152 
153 static void
rebind_resource(struct fd_resource * rsc)154 rebind_resource(struct fd_resource *rsc)
155 {
156 	struct fd_screen *screen = fd_screen(rsc->base.screen);
157 
158 	fd_screen_lock(screen);
159 	fd_resource_lock(rsc);
160 
161 	if (rsc->dirty)
162 		list_for_each_entry (struct fd_context, ctx, &screen->context_list, node)
163 			rebind_resource_in_ctx(ctx, rsc);
164 
165 	fd_resource_unlock(rsc);
166 	fd_screen_unlock(screen);
167 }
168 
169 static inline void
fd_resource_set_bo(struct fd_resource * rsc,struct fd_bo * bo)170 fd_resource_set_bo(struct fd_resource *rsc, struct fd_bo *bo)
171 {
172 	struct fd_screen *screen = fd_screen(rsc->base.screen);
173 
174 	rsc->bo = bo;
175 	rsc->seqno = p_atomic_inc_return(&screen->rsc_seqno);
176 }
177 
178 static void
realloc_bo(struct fd_resource * rsc,uint32_t size)179 realloc_bo(struct fd_resource *rsc, uint32_t size)
180 {
181 	struct pipe_resource *prsc = &rsc->base;
182 	struct fd_screen *screen = fd_screen(rsc->base.screen);
183 	uint32_t flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
184 			DRM_FREEDRENO_GEM_TYPE_KMEM |
185 			COND(prsc->bind & PIPE_BIND_SCANOUT, DRM_FREEDRENO_GEM_SCANOUT);
186 			/* TODO other flags? */
187 
188 	/* if we start using things other than write-combine,
189 	 * be sure to check for PIPE_RESOURCE_FLAG_MAP_COHERENT
190 	 */
191 
192 	if (rsc->bo)
193 		fd_bo_del(rsc->bo);
194 
195 	struct fd_bo *bo = fd_bo_new(screen->dev, size, flags, "%ux%ux%u@%u:%x",
196 			prsc->width0, prsc->height0, prsc->depth0, rsc->layout.cpp, prsc->bind);
197 	fd_resource_set_bo(rsc, bo);
198 
199 	/* Zero out the UBWC area on allocation.  This fixes intermittent failures
200 	 * with UBWC, which I suspect are due to the HW having a hard time
201 	 * interpreting arbitrary values populating the flags buffer when the BO
202 	 * was recycled through the bo cache (instead of fresh allocations from
203 	 * the kernel, which are zeroed).  sleep(1) in this spot didn't work
204 	 * around the issue, but any memset value seems to.
205 	 */
206 	if (rsc->layout.ubwc) {
207 		rsc->needs_ubwc_clear = true;
208 	}
209 
210 	util_range_set_empty(&rsc->valid_buffer_range);
211 	fd_bc_invalidate_resource(rsc, true);
212 }
213 
214 static void
do_blit(struct fd_context * ctx,const struct pipe_blit_info * blit,bool fallback)215 do_blit(struct fd_context *ctx, const struct pipe_blit_info *blit, bool fallback)
216 {
217 	struct pipe_context *pctx = &ctx->base;
218 
219 	/* TODO size threshold too?? */
220 	if (fallback || !fd_blit(pctx, blit)) {
221 		/* do blit on cpu: */
222 		util_resource_copy_region(pctx,
223 				blit->dst.resource, blit->dst.level, blit->dst.box.x,
224 				blit->dst.box.y, blit->dst.box.z,
225 				blit->src.resource, blit->src.level, &blit->src.box);
226 	}
227 }
228 
229 static void
230 flush_resource(struct fd_context *ctx, struct fd_resource *rsc, unsigned usage);
231 
232 /**
233  * @rsc: the resource to shadow
234  * @level: the level to discard (if box != NULL, otherwise ignored)
235  * @box: the box to discard (or NULL if none)
236  * @modifier: the modifier for the new buffer state
237  */
238 static bool
fd_try_shadow_resource(struct fd_context * ctx,struct fd_resource * rsc,unsigned level,const struct pipe_box * box,uint64_t modifier)239 fd_try_shadow_resource(struct fd_context *ctx, struct fd_resource *rsc,
240 		unsigned level, const struct pipe_box *box, uint64_t modifier)
241 {
242 	struct pipe_context *pctx = &ctx->base;
243 	struct pipe_resource *prsc = &rsc->base;
244 	bool fallback = false;
245 
246 	if (prsc->next)
247 		return false;
248 
249 	/* If you have a sequence where there is a single rsc associated
250 	 * with the current render target, and then you end up shadowing
251 	 * that same rsc on the 3d pipe (u_blitter), because of how we
252 	 * swap the new shadow and rsc before the back-blit, you could end
253 	 * up confusing things into thinking that u_blitter's framebuffer
254 	 * state is the same as the current framebuffer state, which has
255 	 * the result of blitting to rsc rather than shadow.
256 	 *
257 	 * Normally we wouldn't want to unconditionally trigger a flush,
258 	 * since that defeats the purpose of shadowing, but this is a
259 	 * case where we'd have to flush anyways.
260 	 */
261 	if (rsc->write_batch == ctx->batch)
262 		flush_resource(ctx, rsc, 0);
263 
264 	/* TODO: somehow munge dimensions and format to copy unsupported
265 	 * render target format to something that is supported?
266 	 */
267 	if (!pctx->screen->is_format_supported(pctx->screen,
268 			prsc->format, prsc->target, prsc->nr_samples,
269 			prsc->nr_storage_samples,
270 			PIPE_BIND_RENDER_TARGET))
271 		fallback = true;
272 
273 	/* do shadowing back-blits on the cpu for buffers: */
274 	if (prsc->target == PIPE_BUFFER)
275 		fallback = true;
276 
277 	bool discard_whole_level = box && util_texrange_covers_whole_level(prsc, level,
278 		box->x, box->y, box->z, box->width, box->height, box->depth);
279 
280 	/* TODO need to be more clever about current level */
281 	if ((prsc->target >= PIPE_TEXTURE_2D) && box && !discard_whole_level)
282 		return false;
283 
284 	struct pipe_resource *pshadow =
285 		pctx->screen->resource_create_with_modifiers(pctx->screen,
286 				prsc, &modifier, 1);
287 
288 	if (!pshadow)
289 		return false;
290 
291 	assert(!ctx->in_shadow);
292 	ctx->in_shadow = true;
293 
294 	/* get rid of any references that batch-cache might have to us (which
295 	 * should empty/destroy rsc->batches hashset)
296 	 */
297 	fd_bc_invalidate_resource(rsc, false);
298 	rebind_resource(rsc);
299 
300 	fd_screen_lock(ctx->screen);
301 
302 	/* Swap the backing bo's, so shadow becomes the old buffer,
303 	 * blit from shadow to new buffer.  From here on out, we
304 	 * cannot fail.
305 	 *
306 	 * Note that we need to do it in this order, otherwise if
307 	 * we go down cpu blit path, the recursive transfer_map()
308 	 * sees the wrong status..
309 	 */
310 	struct fd_resource *shadow = fd_resource(pshadow);
311 
312 	DBG("shadow: %p (%d) -> %p (%d)\n", rsc, rsc->base.reference.count,
313 			shadow, shadow->base.reference.count);
314 
315 	/* TODO valid_buffer_range?? */
316 	swap(rsc->bo,        shadow->bo);
317 	swap(rsc->write_batch,   shadow->write_batch);
318 	swap(rsc->layout, shadow->layout);
319 	rsc->seqno = p_atomic_inc_return(&ctx->screen->rsc_seqno);
320 
321 	/* at this point, the newly created shadow buffer is not referenced
322 	 * by any batches, but the existing rsc (probably) is.  We need to
323 	 * transfer those references over:
324 	 */
325 	debug_assert(shadow->batch_mask == 0);
326 	struct fd_batch *batch;
327 	foreach_batch(batch, &ctx->screen->batch_cache, rsc->batch_mask) {
328 		struct set_entry *entry = _mesa_set_search(batch->resources, rsc);
329 		_mesa_set_remove(batch->resources, entry);
330 		_mesa_set_add(batch->resources, shadow);
331 	}
332 	swap(rsc->batch_mask, shadow->batch_mask);
333 
334 	fd_screen_unlock(ctx->screen);
335 
336 	struct pipe_blit_info blit = {};
337 	blit.dst.resource = prsc;
338 	blit.dst.format   = prsc->format;
339 	blit.src.resource = pshadow;
340 	blit.src.format   = pshadow->format;
341 	blit.mask = util_format_get_mask(prsc->format);
342 	blit.filter = PIPE_TEX_FILTER_NEAREST;
343 
344 #define set_box(field, val) do {     \
345 		blit.dst.field = (val);      \
346 		blit.src.field = (val);      \
347 	} while (0)
348 
349 	/* blit the other levels in their entirety: */
350 	for (unsigned l = 0; l <= prsc->last_level; l++) {
351 		if (box && l == level)
352 			continue;
353 
354 		/* just blit whole level: */
355 		set_box(level, l);
356 		set_box(box.width,  u_minify(prsc->width0, l));
357 		set_box(box.height, u_minify(prsc->height0, l));
358 		set_box(box.depth,  u_minify(prsc->depth0, l));
359 
360 		for (int i = 0; i < prsc->array_size; i++) {
361 			set_box(box.z, i);
362 			do_blit(ctx, &blit, fallback);
363 		}
364 	}
365 
366 	/* deal w/ current level specially, since we might need to split
367 	 * it up into a couple blits:
368 	 */
369 	if (box && !discard_whole_level) {
370 		set_box(level, level);
371 
372 		switch (prsc->target) {
373 		case PIPE_BUFFER:
374 		case PIPE_TEXTURE_1D:
375 			set_box(box.y, 0);
376 			set_box(box.z, 0);
377 			set_box(box.height, 1);
378 			set_box(box.depth, 1);
379 
380 			if (box->x > 0) {
381 				set_box(box.x, 0);
382 				set_box(box.width, box->x);
383 
384 				do_blit(ctx, &blit, fallback);
385 			}
386 			if ((box->x + box->width) < u_minify(prsc->width0, level)) {
387 				set_box(box.x, box->x + box->width);
388 				set_box(box.width, u_minify(prsc->width0, level) - (box->x + box->width));
389 
390 				do_blit(ctx, &blit, fallback);
391 			}
392 			break;
393 		case PIPE_TEXTURE_2D:
394 			/* TODO */
395 		default:
396 			unreachable("TODO");
397 		}
398 	}
399 
400 	ctx->in_shadow = false;
401 
402 	pipe_resource_reference(&pshadow, NULL);
403 
404 	return true;
405 }
406 
407 /**
408  * Uncompress an UBWC compressed buffer "in place".  This works basically
409  * like resource shadowing, creating a new resource, and doing an uncompress
410  * blit, and swapping the state between shadow and original resource so it
411  * appears to the gallium frontends as if nothing changed.
412  */
413 void
fd_resource_uncompress(struct fd_context * ctx,struct fd_resource * rsc)414 fd_resource_uncompress(struct fd_context *ctx, struct fd_resource *rsc)
415 {
416 	bool success =
417 		fd_try_shadow_resource(ctx, rsc, 0, NULL, FD_FORMAT_MOD_QCOM_TILED);
418 
419 	/* shadow should not fail in any cases where we need to uncompress: */
420 	debug_assert(success);
421 }
422 
423 /**
424  * Debug helper to hexdump a resource.
425  */
426 void
fd_resource_dump(struct fd_resource * rsc,const char * name)427 fd_resource_dump(struct fd_resource *rsc, const char *name)
428 {
429 	fd_bo_cpu_prep(rsc->bo, NULL, DRM_FREEDRENO_PREP_READ);
430 	printf("%s: \n", name);
431 	dump_hex(fd_bo_map(rsc->bo), fd_bo_size(rsc->bo));
432 }
433 
434 static struct fd_resource *
fd_alloc_staging(struct fd_context * ctx,struct fd_resource * rsc,unsigned level,const struct pipe_box * box)435 fd_alloc_staging(struct fd_context *ctx, struct fd_resource *rsc,
436 		unsigned level, const struct pipe_box *box)
437 {
438 	struct pipe_context *pctx = &ctx->base;
439 	struct pipe_resource tmpl = rsc->base;
440 
441 	tmpl.width0  = box->width;
442 	tmpl.height0 = box->height;
443 	/* for array textures, box->depth is the array_size, otherwise
444 	 * for 3d textures, it is the depth:
445 	 */
446 	if (tmpl.array_size > 1) {
447 		if (tmpl.target == PIPE_TEXTURE_CUBE)
448 			tmpl.target = PIPE_TEXTURE_2D_ARRAY;
449 		tmpl.array_size = box->depth;
450 		tmpl.depth0 = 1;
451 	} else {
452 		tmpl.array_size = 1;
453 		tmpl.depth0 = box->depth;
454 	}
455 	tmpl.last_level = 0;
456 	tmpl.bind |= PIPE_BIND_LINEAR;
457 
458 	struct pipe_resource *pstaging =
459 		pctx->screen->resource_create(pctx->screen, &tmpl);
460 	if (!pstaging)
461 		return NULL;
462 
463 	return fd_resource(pstaging);
464 }
465 
466 static void
fd_blit_from_staging(struct fd_context * ctx,struct fd_transfer * trans)467 fd_blit_from_staging(struct fd_context *ctx, struct fd_transfer *trans)
468 {
469 	struct pipe_resource *dst = trans->base.resource;
470 	struct pipe_blit_info blit = {};
471 
472 	blit.dst.resource = dst;
473 	blit.dst.format   = dst->format;
474 	blit.dst.level    = trans->base.level;
475 	blit.dst.box      = trans->base.box;
476 	blit.src.resource = trans->staging_prsc;
477 	blit.src.format   = trans->staging_prsc->format;
478 	blit.src.level    = 0;
479 	blit.src.box      = trans->staging_box;
480 	blit.mask = util_format_get_mask(trans->staging_prsc->format);
481 	blit.filter = PIPE_TEX_FILTER_NEAREST;
482 
483 	do_blit(ctx, &blit, false);
484 }
485 
486 static void
fd_blit_to_staging(struct fd_context * ctx,struct fd_transfer * trans)487 fd_blit_to_staging(struct fd_context *ctx, struct fd_transfer *trans)
488 {
489 	struct pipe_resource *src = trans->base.resource;
490 	struct pipe_blit_info blit = {};
491 
492 	blit.src.resource = src;
493 	blit.src.format   = src->format;
494 	blit.src.level    = trans->base.level;
495 	blit.src.box      = trans->base.box;
496 	blit.dst.resource = trans->staging_prsc;
497 	blit.dst.format   = trans->staging_prsc->format;
498 	blit.dst.level    = 0;
499 	blit.dst.box      = trans->staging_box;
500 	blit.mask = util_format_get_mask(trans->staging_prsc->format);
501 	blit.filter = PIPE_TEX_FILTER_NEAREST;
502 
503 	do_blit(ctx, &blit, false);
504 }
505 
fd_resource_transfer_flush_region(struct pipe_context * pctx,struct pipe_transfer * ptrans,const struct pipe_box * box)506 static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
507 		struct pipe_transfer *ptrans,
508 		const struct pipe_box *box)
509 {
510 	struct fd_resource *rsc = fd_resource(ptrans->resource);
511 
512 	if (ptrans->resource->target == PIPE_BUFFER)
513 		util_range_add(&rsc->base, &rsc->valid_buffer_range,
514 					   ptrans->box.x + box->x,
515 					   ptrans->box.x + box->x + box->width);
516 }
517 
518 static void
flush_resource(struct fd_context * ctx,struct fd_resource * rsc,unsigned usage)519 flush_resource(struct fd_context *ctx, struct fd_resource *rsc, unsigned usage)
520 {
521 	struct fd_batch *write_batch = NULL;
522 
523 	fd_screen_lock(ctx->screen);
524 	fd_batch_reference_locked(&write_batch, rsc->write_batch);
525 	fd_screen_unlock(ctx->screen);
526 
527 	if (usage & PIPE_MAP_WRITE) {
528 		struct fd_batch *batch, *batches[32] = {};
529 		uint32_t batch_mask;
530 
531 		/* This is a bit awkward, probably a fd_batch_flush_locked()
532 		 * would make things simpler.. but we need to hold the lock
533 		 * to iterate the batches which reference this resource.  So
534 		 * we must first grab references under a lock, then flush.
535 		 */
536 		fd_screen_lock(ctx->screen);
537 		batch_mask = rsc->batch_mask;
538 		foreach_batch(batch, &ctx->screen->batch_cache, batch_mask)
539 			fd_batch_reference_locked(&batches[batch->idx], batch);
540 		fd_screen_unlock(ctx->screen);
541 
542 		foreach_batch(batch, &ctx->screen->batch_cache, batch_mask)
543 			fd_batch_flush(batch);
544 
545 		foreach_batch(batch, &ctx->screen->batch_cache, batch_mask) {
546 			fd_batch_reference(&batches[batch->idx], NULL);
547 		}
548 		assert(rsc->batch_mask == 0);
549 	} else if (write_batch) {
550 		fd_batch_flush(write_batch);
551 	}
552 
553 	fd_batch_reference(&write_batch, NULL);
554 
555 	assert(!rsc->write_batch);
556 }
557 
558 static void
fd_flush_resource(struct pipe_context * pctx,struct pipe_resource * prsc)559 fd_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
560 {
561 	flush_resource(fd_context(pctx), fd_resource(prsc), PIPE_MAP_READ);
562 }
563 
564 static void
fd_resource_transfer_unmap(struct pipe_context * pctx,struct pipe_transfer * ptrans)565 fd_resource_transfer_unmap(struct pipe_context *pctx,
566 		struct pipe_transfer *ptrans)
567 {
568 	struct fd_context *ctx = fd_context(pctx);
569 	struct fd_resource *rsc = fd_resource(ptrans->resource);
570 	struct fd_transfer *trans = fd_transfer(ptrans);
571 
572 	if (trans->staging_prsc) {
573 		if (ptrans->usage & PIPE_MAP_WRITE)
574 			fd_blit_from_staging(ctx, trans);
575 		pipe_resource_reference(&trans->staging_prsc, NULL);
576 	}
577 
578 	if (!(ptrans->usage & PIPE_MAP_UNSYNCHRONIZED)) {
579 		fd_bo_cpu_fini(rsc->bo);
580 	}
581 
582 	util_range_add(&rsc->base, &rsc->valid_buffer_range,
583 				   ptrans->box.x,
584 				   ptrans->box.x + ptrans->box.width);
585 
586 	pipe_resource_reference(&ptrans->resource, NULL);
587 	slab_free(&ctx->transfer_pool, ptrans);
588 }
589 
590 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)591 fd_resource_transfer_map(struct pipe_context *pctx,
592 		struct pipe_resource *prsc,
593 		unsigned level, unsigned usage,
594 		const struct pipe_box *box,
595 		struct pipe_transfer **pptrans)
596 {
597 	struct fd_context *ctx = fd_context(pctx);
598 	struct fd_resource *rsc = fd_resource(prsc);
599 	struct fd_transfer *trans;
600 	struct pipe_transfer *ptrans;
601 	enum pipe_format format = prsc->format;
602 	uint32_t op = 0;
603 	uint32_t offset;
604 	char *buf;
605 	int ret = 0;
606 
607 	DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage,
608 		box->width, box->height, box->x, box->y);
609 
610 	if ((usage & PIPE_MAP_DIRECTLY) && rsc->layout.tile_mode) {
611 		DBG("CANNOT MAP DIRECTLY!\n");
612 		return NULL;
613 	}
614 
615 	ptrans = slab_alloc(&ctx->transfer_pool);
616 	if (!ptrans)
617 		return NULL;
618 
619 	/* slab_alloc_st() doesn't zero: */
620 	trans = fd_transfer(ptrans);
621 	memset(trans, 0, sizeof(*trans));
622 
623 	pipe_resource_reference(&ptrans->resource, prsc);
624 	ptrans->level = level;
625 	ptrans->usage = usage;
626 	ptrans->box = *box;
627 	ptrans->stride = fd_resource_pitch(rsc, level);
628 	ptrans->layer_stride = fd_resource_layer_stride(rsc, level);
629 
630 	/* we always need a staging texture for tiled buffers:
631 	 *
632 	 * TODO we might sometimes want to *also* shadow the resource to avoid
633 	 * splitting a batch.. for ex, mid-frame texture uploads to a tiled
634 	 * texture.
635 	 */
636 	if (rsc->layout.tile_mode) {
637 		struct fd_resource *staging_rsc;
638 
639 		staging_rsc = fd_alloc_staging(ctx, rsc, level, box);
640 		if (staging_rsc) {
641 			// TODO for PIPE_MAP_READ, need to do untiling blit..
642 			trans->staging_prsc = &staging_rsc->base;
643 			trans->base.stride = fd_resource_pitch(staging_rsc, 0);
644 			trans->base.layer_stride = fd_resource_layer_stride(staging_rsc, 0);
645 			trans->staging_box = *box;
646 			trans->staging_box.x = 0;
647 			trans->staging_box.y = 0;
648 			trans->staging_box.z = 0;
649 
650 			if (usage & PIPE_MAP_READ) {
651 				fd_blit_to_staging(ctx, trans);
652 
653 				fd_bo_cpu_prep(staging_rsc->bo, ctx->pipe,
654 						DRM_FREEDRENO_PREP_READ);
655 			}
656 
657 			buf = fd_bo_map(staging_rsc->bo);
658 			offset = 0;
659 
660 			*pptrans = ptrans;
661 
662 			ctx->stats.staging_uploads++;
663 
664 			return buf;
665 		}
666 	}
667 
668 	if (ctx->in_shadow && !(usage & PIPE_MAP_READ))
669 		usage |= PIPE_MAP_UNSYNCHRONIZED;
670 
671 	if (usage & PIPE_MAP_READ)
672 		op |= DRM_FREEDRENO_PREP_READ;
673 
674 	if (usage & PIPE_MAP_WRITE)
675 		op |= DRM_FREEDRENO_PREP_WRITE;
676 
677 	bool needs_flush = pending(rsc, !!(usage & PIPE_MAP_WRITE));
678 
679 	if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) {
680 		if (needs_flush || fd_resource_busy(rsc, op)) {
681 			rebind_resource(rsc);
682 			realloc_bo(rsc, fd_bo_size(rsc->bo));
683 		}
684 	} else if ((usage & PIPE_MAP_WRITE) &&
685 			   prsc->target == PIPE_BUFFER &&
686 			   !util_ranges_intersect(&rsc->valid_buffer_range,
687 									  box->x, box->x + box->width)) {
688 		/* We are trying to write to a previously uninitialized range. No need
689 		 * to wait.
690 		 */
691 	} else if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
692 		struct fd_batch *write_batch = NULL;
693 
694 		/* hold a reference, so it doesn't disappear under us: */
695 		fd_context_lock(ctx);
696 		fd_batch_reference_locked(&write_batch, rsc->write_batch);
697 		fd_context_unlock(ctx);
698 
699 		if ((usage & PIPE_MAP_WRITE) && write_batch &&
700 				write_batch->back_blit) {
701 			/* if only thing pending is a back-blit, we can discard it: */
702 			fd_batch_reset(write_batch);
703 		}
704 
705 		/* If the GPU is writing to the resource, or if it is reading from the
706 		 * resource and we're trying to write to it, flush the renders.
707 		 */
708 		bool busy = needs_flush || fd_resource_busy(rsc, op);
709 
710 		/* if we need to flush/stall, see if we can make a shadow buffer
711 		 * to avoid this:
712 		 *
713 		 * TODO we could go down this path !reorder && !busy_for_read
714 		 * ie. we only *don't* want to go down this path if the blit
715 		 * will trigger a flush!
716 		 */
717 		if (ctx->screen->reorder && busy && !(usage & PIPE_MAP_READ) &&
718 				(usage & PIPE_MAP_DISCARD_RANGE)) {
719 			/* try shadowing only if it avoids a flush, otherwise staging would
720 			 * be better:
721 			 */
722 			if (needs_flush && fd_try_shadow_resource(ctx, rsc, level,
723 							box, DRM_FORMAT_MOD_LINEAR)) {
724 				needs_flush = busy = false;
725 				ctx->stats.shadow_uploads++;
726 			} else {
727 				struct fd_resource *staging_rsc;
728 
729 				if (needs_flush) {
730 					flush_resource(ctx, rsc, usage);
731 					needs_flush = false;
732 				}
733 
734 				/* in this case, we don't need to shadow the whole resource,
735 				 * since any draw that references the previous contents has
736 				 * already had rendering flushed for all tiles.  So we can
737 				 * use a staging buffer to do the upload.
738 				 */
739 				staging_rsc = fd_alloc_staging(ctx, rsc, level, box);
740 				if (staging_rsc) {
741 					trans->staging_prsc = &staging_rsc->base;
742 					trans->base.stride = fd_resource_pitch(staging_rsc, 0);
743 					trans->base.layer_stride =
744 						fd_resource_layer_stride(staging_rsc, 0);
745 					trans->staging_box = *box;
746 					trans->staging_box.x = 0;
747 					trans->staging_box.y = 0;
748 					trans->staging_box.z = 0;
749 					buf = fd_bo_map(staging_rsc->bo);
750 					offset = 0;
751 
752 					*pptrans = ptrans;
753 
754 					fd_batch_reference(&write_batch, NULL);
755 
756 					ctx->stats.staging_uploads++;
757 
758 					return buf;
759 				}
760 			}
761 		}
762 
763 		if (needs_flush) {
764 			flush_resource(ctx, rsc, usage);
765 			needs_flush = false;
766 		}
767 
768 		fd_batch_reference(&write_batch, NULL);
769 
770 		/* The GPU keeps track of how the various bo's are being used, and
771 		 * will wait if necessary for the proper operation to have
772 		 * completed.
773 		 */
774 		if (busy) {
775 			ret = fd_bo_cpu_prep(rsc->bo, ctx->pipe, op);
776 			if (ret)
777 				goto fail;
778 		}
779 	}
780 
781 	buf = fd_bo_map(rsc->bo);
782 	offset =
783 		box->y / util_format_get_blockheight(format) * ptrans->stride +
784 		box->x / util_format_get_blockwidth(format) * rsc->layout.cpp +
785 		fd_resource_offset(rsc, level, box->z);
786 
787 	if (usage & PIPE_MAP_WRITE)
788 		rsc->valid = true;
789 
790 	*pptrans = ptrans;
791 
792 	return buf + offset;
793 
794 fail:
795 	fd_resource_transfer_unmap(pctx, ptrans);
796 	return NULL;
797 }
798 
799 static void
fd_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * prsc)800 fd_resource_destroy(struct pipe_screen *pscreen,
801 		struct pipe_resource *prsc)
802 {
803 	struct fd_resource *rsc = fd_resource(prsc);
804 	fd_bc_invalidate_resource(rsc, true);
805 	if (rsc->bo)
806 		fd_bo_del(rsc->bo);
807 	if (rsc->lrz)
808 		fd_bo_del(rsc->lrz);
809 	if (rsc->scanout)
810 		renderonly_scanout_destroy(rsc->scanout, fd_screen(pscreen)->ro);
811 
812 	util_range_destroy(&rsc->valid_buffer_range);
813 	simple_mtx_destroy(&rsc->lock);
814 	FREE(rsc);
815 }
816 
817 static uint64_t
fd_resource_modifier(struct fd_resource * rsc)818 fd_resource_modifier(struct fd_resource *rsc)
819 {
820 	if (!rsc->layout.tile_mode)
821 		return DRM_FORMAT_MOD_LINEAR;
822 
823 	if (rsc->layout.ubwc_layer_size)
824 		return DRM_FORMAT_MOD_QCOM_COMPRESSED;
825 
826 	/* TODO invent a modifier for tiled but not UBWC buffers: */
827 	return DRM_FORMAT_MOD_INVALID;
828 }
829 
830 static bool
fd_resource_get_handle(struct pipe_screen * pscreen,struct pipe_context * pctx,struct pipe_resource * prsc,struct winsys_handle * handle,unsigned usage)831 fd_resource_get_handle(struct pipe_screen *pscreen,
832 		struct pipe_context *pctx,
833 		struct pipe_resource *prsc,
834 		struct winsys_handle *handle,
835 		unsigned usage)
836 {
837 	struct fd_resource *rsc = fd_resource(prsc);
838 
839 	handle->modifier = fd_resource_modifier(rsc);
840 
841 	DBG("%p: target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
842 			"nr_samples=%u, usage=%u, bind=%x, flags=%x, modifier=%"PRIx64,
843 			prsc, prsc->target, util_format_name(prsc->format),
844 			prsc->width0, prsc->height0, prsc->depth0,
845 			prsc->array_size, prsc->last_level, prsc->nr_samples,
846 			prsc->usage, prsc->bind, prsc->flags,
847 			handle->modifier);
848 
849 	return fd_screen_bo_get_handle(pscreen, rsc->bo, rsc->scanout,
850 			fd_resource_pitch(rsc, 0), handle);
851 }
852 
853 /* special case to resize query buf after allocated.. */
854 void
fd_resource_resize(struct pipe_resource * prsc,uint32_t sz)855 fd_resource_resize(struct pipe_resource *prsc, uint32_t sz)
856 {
857 	struct fd_resource *rsc = fd_resource(prsc);
858 
859 	debug_assert(prsc->width0 == 0);
860 	debug_assert(prsc->target == PIPE_BUFFER);
861 	debug_assert(prsc->bind == PIPE_BIND_QUERY_BUFFER);
862 
863 	prsc->width0 = sz;
864 	realloc_bo(rsc, fd_screen(prsc->screen)->setup_slices(rsc));
865 }
866 
867 static void
fd_resource_layout_init(struct pipe_resource * prsc)868 fd_resource_layout_init(struct pipe_resource *prsc)
869 {
870 	struct fd_resource *rsc = fd_resource(prsc);
871 	struct fdl_layout *layout = &rsc->layout;
872 
873 	layout->format = prsc->format;
874 
875 	layout->width0 = prsc->width0;
876 	layout->height0 = prsc->height0;
877 	layout->depth0 = prsc->depth0;
878 
879 	layout->cpp = util_format_get_blocksize(prsc->format);
880 	layout->cpp *= fd_resource_nr_samples(prsc);
881 	layout->cpp_shift = ffs(layout->cpp) - 1;
882 }
883 
884 /**
885  * Helper that allocates a resource and resolves its layout (but doesn't
886  * allocate its bo).
887  *
888  * It returns a pipe_resource (as fd_resource_create_with_modifiers()
889  * would do), and also bo's minimum required size as an output argument.
890  */
891 static struct pipe_resource *
fd_resource_allocate_and_resolve(struct pipe_screen * pscreen,const struct pipe_resource * tmpl,const uint64_t * modifiers,int count,uint32_t * psize)892 fd_resource_allocate_and_resolve(struct pipe_screen *pscreen,
893 		const struct pipe_resource *tmpl,
894 		const uint64_t *modifiers, int count, uint32_t *psize)
895 {
896 	struct fd_screen *screen = fd_screen(pscreen);
897 	struct fd_resource *rsc;
898 	struct pipe_resource *prsc;
899 	enum pipe_format format = tmpl->format;
900 	uint32_t size;
901 
902 	rsc = CALLOC_STRUCT(fd_resource);
903 	prsc = &rsc->base;
904 
905 	DBG("%p: target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
906 			"nr_samples=%u, usage=%u, bind=%x, flags=%x", prsc,
907 			tmpl->target, util_format_name(format),
908 			tmpl->width0, tmpl->height0, tmpl->depth0,
909 			tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
910 			tmpl->usage, tmpl->bind, tmpl->flags);
911 
912 	if (!rsc)
913 		return NULL;
914 
915 	*prsc = *tmpl;
916 	fd_resource_layout_init(prsc);
917 
918 #define LINEAR \
919 	(PIPE_BIND_SCANOUT | \
920 	 PIPE_BIND_LINEAR  | \
921 	 PIPE_BIND_DISPLAY_TARGET)
922 
923 	bool linear = drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count);
924 	if (tmpl->bind & LINEAR)
925 		linear = true;
926 
927 	if (fd_mesa_debug & FD_DBG_NOTILE)
928 		linear = true;
929 
930 	/* Normally, for non-shared buffers, allow buffer compression if
931 	 * not shared, otherwise only allow if QCOM_COMPRESSED modifier
932 	 * is requested:
933 	 *
934 	 * TODO we should probably also limit tiled in a similar way,
935 	 * except we don't have a format modifier for tiled.  (We probably
936 	 * should.)
937 	 */
938 	bool allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_INVALID, modifiers, count);
939 	if (tmpl->bind & PIPE_BIND_SHARED) {
940 		allow_ubwc = drm_find_modifier(DRM_FORMAT_MOD_QCOM_COMPRESSED, modifiers, count);
941 		if (!allow_ubwc) {
942 			linear = true;
943 		}
944 	}
945 
946 	allow_ubwc &= !(fd_mesa_debug & FD_DBG_NOUBWC);
947 
948 	pipe_reference_init(&prsc->reference, 1);
949 
950 	prsc->screen = pscreen;
951 
952 	if (screen->tile_mode &&
953 			(tmpl->target != PIPE_BUFFER) &&
954 			!linear) {
955 		rsc->layout.tile_mode = screen->tile_mode(prsc);
956 	}
957 
958 	util_range_init(&rsc->valid_buffer_range);
959 
960 	simple_mtx_init(&rsc->lock, mtx_plain);
961 
962 	rsc->internal_format = format;
963 
964 	rsc->layout.ubwc = rsc->layout.tile_mode && is_a6xx(screen) && allow_ubwc;
965 
966 	if (prsc->target == PIPE_BUFFER) {
967 		assert(prsc->format == PIPE_FORMAT_R8_UNORM);
968 		size = prsc->width0;
969 		fdl_layout_buffer(&rsc->layout, size);
970 	} else {
971 		size = screen->setup_slices(rsc);
972 	}
973 
974 	/* special case for hw-query buffer, which we need to allocate before we
975 	 * know the size:
976 	 */
977 	if (size == 0) {
978 		/* note, semi-intention == instead of & */
979 		debug_assert(prsc->bind == PIPE_BIND_QUERY_BUFFER);
980 		*psize = 0;
981 		return prsc;
982 	}
983 
984 	/* Set the layer size if the (non-a6xx) backend hasn't done so. */
985 	if (rsc->layout.layer_first && !rsc->layout.layer_size) {
986 		rsc->layout.layer_size = align(size, 4096);
987 		size = rsc->layout.layer_size * prsc->array_size;
988 	}
989 
990 	if (fd_mesa_debug & FD_DBG_LAYOUT)
991 		fdl_dump_layout(&rsc->layout);
992 
993 	/* Hand out the resolved size. */
994 	if (psize)
995 		*psize = size;
996 
997 	return prsc;
998 }
999 
1000 /**
1001  * Create a new texture object, using the given template info.
1002  */
1003 static struct pipe_resource *
fd_resource_create_with_modifiers(struct pipe_screen * pscreen,const struct pipe_resource * tmpl,const uint64_t * modifiers,int count)1004 fd_resource_create_with_modifiers(struct pipe_screen *pscreen,
1005 		const struct pipe_resource *tmpl,
1006 		const uint64_t *modifiers, int count)
1007 {
1008 	struct fd_screen *screen = fd_screen(pscreen);
1009 	struct fd_resource *rsc;
1010 	struct pipe_resource *prsc;
1011 	uint32_t size;
1012 
1013 	/* when using kmsro, scanout buffers are allocated on the display device
1014 	 * create_with_modifiers() doesn't give us usage flags, so we have to
1015 	 * assume that all calls with modifiers are scanout-possible
1016 	 */
1017 	if (screen->ro &&
1018 		((tmpl->bind & PIPE_BIND_SCANOUT) ||
1019 		 !(count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID))) {
1020 		struct pipe_resource scanout_templat = *tmpl;
1021 		struct renderonly_scanout *scanout;
1022 		struct winsys_handle handle;
1023 
1024 		/* note: alignment is wrong for a6xx */
1025 		scanout_templat.width0 = align(tmpl->width0, screen->info.gmem_align_w);
1026 
1027 		scanout = renderonly_scanout_for_resource(&scanout_templat,
1028 												  screen->ro, &handle);
1029 		if (!scanout)
1030 			return NULL;
1031 
1032 		renderonly_scanout_destroy(scanout, screen->ro);
1033 
1034 		assert(handle.type == WINSYS_HANDLE_TYPE_FD);
1035 		rsc = fd_resource(pscreen->resource_from_handle(pscreen, tmpl,
1036 														&handle,
1037 														PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
1038 		close(handle.handle);
1039 		if (!rsc)
1040 			return NULL;
1041 
1042 		return &rsc->base;
1043 	}
1044 
1045 	prsc = fd_resource_allocate_and_resolve(pscreen, tmpl, modifiers, count, &size);
1046 	if (!prsc)
1047 		return NULL;
1048 	rsc = fd_resource(prsc);
1049 
1050 	realloc_bo(rsc, size);
1051 	if (!rsc->bo)
1052 		goto fail;
1053 
1054 	return prsc;
1055 fail:
1056 	fd_resource_destroy(pscreen, prsc);
1057 	return NULL;
1058 }
1059 
1060 static struct pipe_resource *
fd_resource_create(struct pipe_screen * pscreen,const struct pipe_resource * tmpl)1061 fd_resource_create(struct pipe_screen *pscreen,
1062 		const struct pipe_resource *tmpl)
1063 {
1064 	const uint64_t mod = DRM_FORMAT_MOD_INVALID;
1065 	return fd_resource_create_with_modifiers(pscreen, tmpl, &mod, 1);
1066 }
1067 
1068 /**
1069  * Create a texture from a winsys_handle. The handle is often created in
1070  * another process by first creating a pipe texture and then calling
1071  * resource_get_handle.
1072  */
1073 static struct pipe_resource *
fd_resource_from_handle(struct pipe_screen * pscreen,const struct pipe_resource * tmpl,struct winsys_handle * handle,unsigned usage)1074 fd_resource_from_handle(struct pipe_screen *pscreen,
1075 		const struct pipe_resource *tmpl,
1076 		struct winsys_handle *handle, unsigned usage)
1077 {
1078 	struct fd_screen *screen = fd_screen(pscreen);
1079 	struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
1080 
1081 	if (!rsc)
1082 		return NULL;
1083 
1084 	struct fdl_slice *slice = fd_resource_slice(rsc, 0);
1085 	struct pipe_resource *prsc = &rsc->base;
1086 
1087 	DBG("%p: target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, "
1088 			"nr_samples=%u, usage=%u, bind=%x, flags=%x, modifier=%"PRIx64,
1089 			prsc, tmpl->target, util_format_name(tmpl->format),
1090 			tmpl->width0, tmpl->height0, tmpl->depth0,
1091 			tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
1092 			tmpl->usage, tmpl->bind, tmpl->flags,
1093 			handle->modifier);
1094 
1095 	*prsc = *tmpl;
1096 	fd_resource_layout_init(prsc);
1097 
1098 	pipe_reference_init(&prsc->reference, 1);
1099 
1100 	prsc->screen = pscreen;
1101 
1102 	util_range_init(&rsc->valid_buffer_range);
1103 
1104 	simple_mtx_init(&rsc->lock, mtx_plain);
1105 
1106 	struct fd_bo *bo = fd_screen_bo_from_handle(pscreen, handle);
1107 	if (!bo)
1108 		goto fail;
1109 
1110 	fd_resource_set_bo(rsc, bo);
1111 
1112 	rsc->internal_format = tmpl->format;
1113 	rsc->layout.pitch0 = handle->stride;
1114 	slice->offset = handle->offset;
1115 	slice->size0 = handle->stride * prsc->height0;
1116 
1117 	/* use a pitchalign of gmem_align_w pixels, because GMEM resolve for
1118 	 * lower alignments is not implemented (but possible for a6xx at least)
1119 	 *
1120 	 * for UBWC-enabled resources, layout_resource_for_modifier will further
1121 	 * validate the pitch and set the right pitchalign
1122 	 */
1123 	rsc->layout.pitchalign =
1124 		fdl_cpp_shift(&rsc->layout) + util_logbase2(screen->info.gmem_align_w);
1125 
1126 	/* apply the minimum pitchalign (note: actually 4 for a3xx but doesn't matter) */
1127 	if (is_a6xx(screen) || is_a5xx(screen))
1128 		rsc->layout.pitchalign = MAX2(rsc->layout.pitchalign, 6);
1129 	else
1130 		rsc->layout.pitchalign = MAX2(rsc->layout.pitchalign, 5);
1131 
1132 	if (rsc->layout.pitch0 < (prsc->width0 * rsc->layout.cpp) ||
1133 		fd_resource_pitch(rsc, 0) != rsc->layout.pitch0)
1134 		goto fail;
1135 
1136 	assert(rsc->layout.cpp);
1137 
1138 	if (screen->layout_resource_for_modifier(rsc, handle->modifier) < 0)
1139 		goto fail;
1140 
1141 	if (screen->ro) {
1142 		rsc->scanout =
1143 			renderonly_create_gpu_import_for_resource(prsc, screen->ro, NULL);
1144 		/* failure is expected in some cases.. */
1145 	}
1146 
1147 	rsc->valid = true;
1148 
1149 	return prsc;
1150 
1151 fail:
1152 	fd_resource_destroy(pscreen, prsc);
1153 	return NULL;
1154 }
1155 
1156 bool
fd_render_condition_check(struct pipe_context * pctx)1157 fd_render_condition_check(struct pipe_context *pctx)
1158 {
1159 	struct fd_context *ctx = fd_context(pctx);
1160 
1161 	if (!ctx->cond_query)
1162 		return true;
1163 
1164 	union pipe_query_result res = { 0 };
1165 	bool wait =
1166 		ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT &&
1167 		ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
1168 
1169 	if (pctx->get_query_result(pctx, ctx->cond_query, wait, &res))
1170 			return (bool)res.u64 != ctx->cond_cond;
1171 
1172 	return true;
1173 }
1174 
1175 static void
fd_invalidate_resource(struct pipe_context * pctx,struct pipe_resource * prsc)1176 fd_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
1177 {
1178 	struct fd_context *ctx = fd_context(pctx);
1179 	struct fd_resource *rsc = fd_resource(prsc);
1180 
1181 	/*
1182 	 * TODO I guess we could track that the resource is invalidated and
1183 	 * use that as a hint to realloc rather than stall in _transfer_map(),
1184 	 * even in the non-DISCARD_WHOLE_RESOURCE case?
1185 	 *
1186 	 * Note: we set dirty bits to trigger invalidate logic fd_draw_vbo
1187 	 */
1188 
1189 	if (rsc->write_batch) {
1190 		struct fd_batch *batch = rsc->write_batch;
1191 		struct pipe_framebuffer_state *pfb = &batch->framebuffer;
1192 
1193 		if (pfb->zsbuf && pfb->zsbuf->texture == prsc) {
1194 			batch->resolve &= ~(FD_BUFFER_DEPTH | FD_BUFFER_STENCIL);
1195 			ctx->dirty |= FD_DIRTY_ZSA;
1196 		}
1197 
1198 		for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
1199 			if (pfb->cbufs[i] && pfb->cbufs[i]->texture == prsc) {
1200 				batch->resolve &= ~(PIPE_CLEAR_COLOR0 << i);
1201 				ctx->dirty |= FD_DIRTY_FRAMEBUFFER;
1202 			}
1203 		}
1204 	}
1205 
1206 	rsc->valid = false;
1207 }
1208 
1209 static enum pipe_format
fd_resource_get_internal_format(struct pipe_resource * prsc)1210 fd_resource_get_internal_format(struct pipe_resource *prsc)
1211 {
1212 	return fd_resource(prsc)->internal_format;
1213 }
1214 
1215 static void
fd_resource_set_stencil(struct pipe_resource * prsc,struct pipe_resource * stencil)1216 fd_resource_set_stencil(struct pipe_resource *prsc,
1217 		struct pipe_resource *stencil)
1218 {
1219 	fd_resource(prsc)->stencil = fd_resource(stencil);
1220 }
1221 
1222 static struct pipe_resource *
fd_resource_get_stencil(struct pipe_resource * prsc)1223 fd_resource_get_stencil(struct pipe_resource *prsc)
1224 {
1225 	struct fd_resource *rsc = fd_resource(prsc);
1226 	if (rsc->stencil)
1227 		return &rsc->stencil->base;
1228 	return NULL;
1229 }
1230 
1231 static const struct u_transfer_vtbl transfer_vtbl = {
1232 		.resource_create          = fd_resource_create,
1233 		.resource_destroy         = fd_resource_destroy,
1234 		.transfer_map             = fd_resource_transfer_map,
1235 		.transfer_flush_region    = fd_resource_transfer_flush_region,
1236 		.transfer_unmap           = fd_resource_transfer_unmap,
1237 		.get_internal_format      = fd_resource_get_internal_format,
1238 		.set_stencil              = fd_resource_set_stencil,
1239 		.get_stencil              = fd_resource_get_stencil,
1240 };
1241 
1242 static const uint64_t supported_modifiers[] = {
1243 	DRM_FORMAT_MOD_LINEAR,
1244 };
1245 
1246 static int
fd_layout_resource_for_modifier(struct fd_resource * rsc,uint64_t modifier)1247 fd_layout_resource_for_modifier(struct fd_resource *rsc, uint64_t modifier)
1248 {
1249 	switch (modifier) {
1250 	case DRM_FORMAT_MOD_LINEAR:
1251 		/* The dri gallium frontend will pass DRM_FORMAT_MOD_INVALID to us
1252 		 * when it's called through any of the non-modifier BO create entry
1253 		 * points.  Other drivers will determine tiling from the kernel or
1254 		 * other legacy backchannels, but for freedreno it just means
1255 		 * LINEAR. */
1256 	case DRM_FORMAT_MOD_INVALID:
1257 		return 0;
1258 	default:
1259 		return -1;
1260 	}
1261 }
1262 
1263 static struct pipe_resource *
fd_resource_from_memobj(struct pipe_screen * pscreen,const struct pipe_resource * tmpl,struct pipe_memory_object * pmemobj,uint64_t offset)1264 fd_resource_from_memobj(struct pipe_screen *pscreen,
1265 						const struct pipe_resource *tmpl,
1266 						struct pipe_memory_object *pmemobj,
1267 						uint64_t offset)
1268 {
1269 	struct fd_screen *screen = fd_screen(pscreen);
1270 	struct fd_memory_object *memobj = fd_memory_object(pmemobj);
1271 	struct pipe_resource *prsc;
1272 	struct fd_resource *rsc;
1273 	uint32_t size;
1274 	assert(memobj->bo);
1275 
1276 	/* We shouldn't get a scanout buffer here. */
1277 	assert(!(tmpl->bind & PIPE_BIND_SCANOUT));
1278 
1279 	uint64_t modifiers = DRM_FORMAT_MOD_INVALID;
1280 	if (tmpl->bind & PIPE_BIND_LINEAR) {
1281 		modifiers = DRM_FORMAT_MOD_LINEAR;
1282 	} else if (is_a6xx(screen) && tmpl->width0 >= FDL_MIN_UBWC_WIDTH) {
1283 		modifiers = DRM_FORMAT_MOD_QCOM_COMPRESSED;
1284 	}
1285 
1286 	/* Allocate new pipe resource. */
1287 	prsc = fd_resource_allocate_and_resolve(pscreen, tmpl, &modifiers, 1, &size);
1288 	if (!prsc)
1289 		return NULL;
1290 	rsc = fd_resource(prsc);
1291 
1292 	/* bo's size has to be large enough, otherwise cleanup resource and fail
1293 	 * gracefully.
1294 	 */
1295 	if (fd_bo_size(memobj->bo) < size) {
1296 		fd_resource_destroy(pscreen, prsc);
1297 		return NULL;
1298 	}
1299 
1300 	/* Share the bo with the memory object. */
1301 	fd_resource_set_bo(rsc, fd_bo_ref(memobj->bo));
1302 
1303 	return prsc;
1304 }
1305 
1306 static struct pipe_memory_object *
fd_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * whandle,bool dedicated)1307 fd_memobj_create_from_handle(struct pipe_screen *pscreen,
1308 							 struct winsys_handle *whandle,
1309 							 bool dedicated)
1310 {
1311 	struct fd_memory_object *memobj = CALLOC_STRUCT(fd_memory_object);
1312 	if (!memobj)
1313 		return NULL;
1314 
1315 	struct fd_bo *bo = fd_screen_bo_from_handle(pscreen, whandle);
1316 	if (!bo) {
1317 		free(memobj);
1318 		return NULL;
1319 	}
1320 
1321 	memobj->b.dedicated = dedicated;
1322 	memobj->bo = bo;
1323 
1324 	return &memobj->b;
1325 }
1326 
1327 static void
fd_memobj_destroy(struct pipe_screen * pscreen,struct pipe_memory_object * pmemobj)1328 fd_memobj_destroy(struct pipe_screen *pscreen,
1329 		struct pipe_memory_object *pmemobj)
1330 {
1331 	struct fd_memory_object *memobj = fd_memory_object(pmemobj);
1332 
1333 	assert(memobj->bo);
1334 	fd_bo_del(memobj->bo);
1335 
1336 	free(pmemobj);
1337 }
1338 
1339 void
fd_resource_screen_init(struct pipe_screen * pscreen)1340 fd_resource_screen_init(struct pipe_screen *pscreen)
1341 {
1342 	struct fd_screen *screen = fd_screen(pscreen);
1343 	bool fake_rgtc = screen->gpu_id < 400;
1344 
1345 	pscreen->resource_create = u_transfer_helper_resource_create;
1346 	/* NOTE: u_transfer_helper does not yet support the _with_modifiers()
1347 	 * variant:
1348 	 */
1349 	pscreen->resource_create_with_modifiers = fd_resource_create_with_modifiers;
1350 	pscreen->resource_from_handle = fd_resource_from_handle;
1351 	pscreen->resource_get_handle = fd_resource_get_handle;
1352 	pscreen->resource_destroy = u_transfer_helper_resource_destroy;
1353 
1354 	pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl,
1355 			true, false, fake_rgtc, true);
1356 
1357 	if (!screen->layout_resource_for_modifier)
1358 		screen->layout_resource_for_modifier = fd_layout_resource_for_modifier;
1359 	if (!screen->supported_modifiers) {
1360 		screen->supported_modifiers = supported_modifiers;
1361 		screen->num_supported_modifiers = ARRAY_SIZE(supported_modifiers);
1362 	}
1363 
1364 	/* GL_EXT_memory_object */
1365 	pscreen->memobj_create_from_handle = fd_memobj_create_from_handle;
1366 	pscreen->memobj_destroy = fd_memobj_destroy;
1367 	pscreen->resource_from_memobj = fd_resource_from_memobj;
1368 }
1369 
1370 static void
fd_get_sample_position(struct pipe_context * context,unsigned sample_count,unsigned sample_index,float * pos_out)1371 fd_get_sample_position(struct pipe_context *context,
1372                          unsigned sample_count, unsigned sample_index,
1373                          float *pos_out)
1374 {
1375 	/* The following is copied from nouveau/nv50 except for position
1376 	 * values, which are taken from blob driver */
1377 	static const uint8_t pos1[1][2] = { { 0x8, 0x8 } };
1378 	static const uint8_t pos2[2][2] = {
1379 		{ 0xc, 0xc }, { 0x4, 0x4 } };
1380 	static const uint8_t pos4[4][2] = {
1381 		{ 0x6, 0x2 }, { 0xe, 0x6 },
1382 		{ 0x2, 0xa }, { 0xa, 0xe } };
1383 	/* TODO needs to be verified on supported hw */
1384 	static const uint8_t pos8[8][2] = {
1385 		{ 0x9, 0x5 }, { 0x7, 0xb },
1386 		{ 0xd, 0x9 }, { 0x5, 0x3 },
1387 		{ 0x3, 0xd }, { 0x1, 0x7 },
1388 		{ 0xb, 0xf }, { 0xf, 0x1 } };
1389 
1390 	const uint8_t (*ptr)[2];
1391 
1392 	switch (sample_count) {
1393 	case 1:
1394 		ptr = pos1;
1395 		break;
1396 	case 2:
1397 		ptr = pos2;
1398 		break;
1399 	case 4:
1400 		ptr = pos4;
1401 		break;
1402 	case 8:
1403 		ptr = pos8;
1404 		break;
1405 	default:
1406 		assert(0);
1407 		return;
1408 	}
1409 
1410 	pos_out[0] = ptr[sample_index][0] / 16.0f;
1411 	pos_out[1] = ptr[sample_index][1] / 16.0f;
1412 }
1413 
1414 static void
fd_blit_pipe(struct pipe_context * pctx,const struct pipe_blit_info * blit_info)1415 fd_blit_pipe(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
1416 {
1417 	/* wrap fd_blit to return void */
1418 	fd_blit(pctx, blit_info);
1419 }
1420 
1421 void
fd_resource_context_init(struct pipe_context * pctx)1422 fd_resource_context_init(struct pipe_context *pctx)
1423 {
1424 	pctx->transfer_map = u_transfer_helper_transfer_map;
1425 	pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region;
1426 	pctx->transfer_unmap = u_transfer_helper_transfer_unmap;
1427 	pctx->buffer_subdata = u_default_buffer_subdata;
1428 	pctx->texture_subdata = u_default_texture_subdata;
1429 	pctx->create_surface = fd_create_surface;
1430 	pctx->surface_destroy = fd_surface_destroy;
1431 	pctx->resource_copy_region = fd_resource_copy_region;
1432 	pctx->blit = fd_blit_pipe;
1433 	pctx->flush_resource = fd_flush_resource;
1434 	pctx->invalidate_resource = fd_invalidate_resource;
1435 	pctx->get_sample_position = fd_get_sample_position;
1436 }
1437