Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
 
3
/*
4
 * Copyright (C) 2012 Rob Clark 
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 
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
#include "util/u_surface.h"
34
 
35
#include "freedreno_resource.h"
36
#include "freedreno_screen.h"
37
#include "freedreno_surface.h"
38
#include "freedreno_context.h"
39
#include "freedreno_util.h"
40
 
41
static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
42
		struct pipe_transfer *ptrans,
43
		const struct pipe_box *box)
44
{
45
	struct fd_context *ctx = fd_context(pctx);
46
	struct fd_resource *rsc = fd_resource(ptrans->resource);
47
 
48
	if (rsc->dirty)
49
		fd_context_render(pctx);
50
 
51
	if (rsc->timestamp) {
52
		fd_pipe_wait(ctx->screen->pipe, rsc->timestamp);
53
		rsc->timestamp = 0;
54
	}
55
}
56
 
57
static void
58
fd_resource_transfer_unmap(struct pipe_context *pctx,
59
		struct pipe_transfer *ptrans)
60
{
61
	struct fd_context *ctx = fd_context(pctx);
4401 Serge 62
	struct fd_resource *rsc = fd_resource(ptrans->resource);
63
	if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED))
64
		fd_bo_cpu_fini(rsc->bo);
4358 Serge 65
	pipe_resource_reference(&ptrans->resource, NULL);
66
	util_slab_free(&ctx->transfer_pool, ptrans);
67
}
68
 
69
static void *
70
fd_resource_transfer_map(struct pipe_context *pctx,
71
		struct pipe_resource *prsc,
72
		unsigned level, unsigned usage,
73
		const struct pipe_box *box,
74
		struct pipe_transfer **pptrans)
75
{
76
	struct fd_context *ctx = fd_context(pctx);
77
	struct fd_resource *rsc = fd_resource(prsc);
78
	struct pipe_transfer *ptrans = util_slab_alloc(&ctx->transfer_pool);
79
	enum pipe_format format = prsc->format;
4401 Serge 80
	uint32_t op = 0;
4358 Serge 81
	char *buf;
82
 
83
	if (!ptrans)
84
		return NULL;
85
 
4401 Serge 86
	/* util_slab_alloc() doesn't zero: */
4358 Serge 87
	memset(ptrans, 0, sizeof(*ptrans));
88
 
89
	pipe_resource_reference(&ptrans->resource, prsc);
90
	ptrans->level = level;
91
	ptrans->usage = usage;
92
	ptrans->box = *box;
93
	ptrans->stride = rsc->pitch * rsc->cpp;
94
	ptrans->layer_stride = ptrans->stride;
95
 
96
	/* some state trackers (at least XA) don't do this.. */
4401 Serge 97
	if (!(usage & PIPE_TRANSFER_FLUSH_EXPLICIT))
98
		fd_resource_transfer_flush_region(pctx, ptrans, box);
4358 Serge 99
 
100
	buf = fd_bo_map(rsc->bo);
101
	if (!buf) {
102
		fd_resource_transfer_unmap(pctx, ptrans);
103
		return NULL;
104
	}
105
 
4401 Serge 106
	if (usage & PIPE_TRANSFER_READ)
107
		op |= DRM_FREEDRENO_PREP_READ;
108
 
109
	if (usage & PIPE_TRANSFER_WRITE)
110
		op |= DRM_FREEDRENO_PREP_WRITE;
111
 
112
	if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED))
113
		fd_bo_cpu_prep(rsc->bo, ctx->screen->pipe, op);
114
 
4358 Serge 115
	*pptrans = ptrans;
116
 
117
	return buf +
118
		box->y / util_format_get_blockheight(format) * ptrans->stride +
119
		box->x / util_format_get_blockwidth(format) * rsc->cpp;
120
}
121
 
122
static void
123
fd_resource_destroy(struct pipe_screen *pscreen,
124
		struct pipe_resource *prsc)
125
{
126
	struct fd_resource *rsc = fd_resource(prsc);
127
	fd_bo_del(rsc->bo);
128
	FREE(rsc);
129
}
130
 
131
static boolean
132
fd_resource_get_handle(struct pipe_screen *pscreen,
133
		struct pipe_resource *prsc,
134
		struct winsys_handle *handle)
135
{
136
	struct fd_resource *rsc = fd_resource(prsc);
137
 
138
	return fd_screen_bo_get_handle(pscreen, rsc->bo,
139
			rsc->pitch * rsc->cpp, handle);
140
}
141
 
142
 
143
static const struct u_resource_vtbl fd_resource_vtbl = {
144
		.resource_get_handle      = fd_resource_get_handle,
145
		.resource_destroy         = fd_resource_destroy,
146
		.transfer_map             = fd_resource_transfer_map,
147
		.transfer_flush_region    = fd_resource_transfer_flush_region,
148
		.transfer_unmap           = fd_resource_transfer_unmap,
149
		.transfer_inline_write    = u_default_transfer_inline_write,
150
};
151
 
152
/**
153
 * Create a new texture object, using the given template info.
154
 */
155
static struct pipe_resource *
156
fd_resource_create(struct pipe_screen *pscreen,
157
		const struct pipe_resource *tmpl)
158
{
159
	struct fd_screen *screen = fd_screen(pscreen);
160
	struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
161
	struct pipe_resource *prsc = &rsc->base.b;
162
	uint32_t flags, size;
163
 
164
	DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, "
165
			"nr_samples=%u, usage=%u, bind=%x, flags=%x",
166
			tmpl->target, util_format_name(tmpl->format),
167
			tmpl->width0, tmpl->height0, tmpl->depth0,
168
			tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
169
			tmpl->usage, tmpl->bind, tmpl->flags);
170
 
171
	if (!rsc)
172
		return NULL;
173
 
174
	*prsc = *tmpl;
175
 
176
	pipe_reference_init(&prsc->reference, 1);
177
	prsc->screen = pscreen;
178
 
179
	rsc->base.vtbl = &fd_resource_vtbl;
180
	rsc->pitch = align(tmpl->width0, 32);
181
	rsc->cpp = util_format_get_blocksize(tmpl->format);
182
 
183
	assert(rsc->cpp);
184
 
185
	size = rsc->pitch * tmpl->height0 * rsc->cpp;
186
	flags = DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
187
			DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */
188
 
189
	rsc->bo = fd_bo_new(screen->dev, size, flags);
190
 
191
	return prsc;
192
}
193
 
194
/**
195
 * Create a texture from a winsys_handle. The handle is often created in
196
 * another process by first creating a pipe texture and then calling
197
 * resource_get_handle.
198
 */
199
static struct pipe_resource *
200
fd_resource_from_handle(struct pipe_screen *pscreen,
201
		const struct pipe_resource *tmpl,
202
		struct winsys_handle *handle)
203
{
204
	struct fd_resource *rsc = CALLOC_STRUCT(fd_resource);
205
	struct pipe_resource *prsc = &rsc->base.b;
206
 
207
	DBG("target=%d, format=%s, %ux%u@%u, array_size=%u, last_level=%u, "
208
			"nr_samples=%u, usage=%u, bind=%x, flags=%x",
209
			tmpl->target, util_format_name(tmpl->format),
210
			tmpl->width0, tmpl->height0, tmpl->depth0,
211
			tmpl->array_size, tmpl->last_level, tmpl->nr_samples,
212
			tmpl->usage, tmpl->bind, tmpl->flags);
213
 
214
	if (!rsc)
215
		return NULL;
216
 
217
	*prsc = *tmpl;
218
 
219
	pipe_reference_init(&prsc->reference, 1);
220
	prsc->screen = pscreen;
221
 
222
	rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &rsc->pitch);
223
 
224
	rsc->base.vtbl = &fd_resource_vtbl;
225
	rsc->cpp = util_format_get_blocksize(tmpl->format);
226
	rsc->pitch /= rsc->cpp;
227
 
228
	assert(rsc->cpp);
229
 
230
	return prsc;
231
}
232
 
233
static bool render_blit(struct pipe_context *pctx, struct pipe_blit_info *info);
234
 
235
/**
236
 * Copy a block of pixels from one resource to another.
237
 * The resource must be of the same format.
238
 * Resources with nr_samples > 1 are not allowed.
239
 */
240
static void
241
fd_resource_copy_region(struct pipe_context *pctx,
242
		struct pipe_resource *dst,
243
		unsigned dst_level,
244
		unsigned dstx, unsigned dsty, unsigned dstz,
245
		struct pipe_resource *src,
246
		unsigned src_level,
247
		const struct pipe_box *src_box)
248
{
249
	/* TODO if we have 2d core, or other DMA engine that could be used
250
	 * for simple copies and reasonably easily synchronized with the 3d
251
	 * core, this is where we'd plug it in..
252
	 */
253
	struct pipe_blit_info info = {
254
		.dst = {
255
			.resource = dst,
256
			.box = {
257
				.x      = dstx,
258
				.y      = dsty,
259
				.z      = dstz,
260
				.width  = src_box->width,
261
				.height = src_box->height,
262
				.depth  = src_box->depth,
263
			},
264
			.format = util_format_linear(dst->format),
265
		},
266
		.src = {
267
			.resource = src,
268
			.box      = *src_box,
269
			.format   = util_format_linear(src->format),
270
		},
271
		.mask = PIPE_MASK_RGBA,
272
		.filter = PIPE_TEX_FILTER_NEAREST,
273
	};
274
	render_blit(pctx, &info);
275
}
276
 
277
/* Optimal hardware path for blitting pixels.
278
 * Scaling, format conversion, up- and downsampling (resolve) are allowed.
279
 */
280
static void
281
fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
282
{
283
	struct pipe_blit_info info = *blit_info;
284
 
285
	if (info.src.resource->nr_samples > 1 &&
286
			info.dst.resource->nr_samples <= 1 &&
287
			!util_format_is_depth_or_stencil(info.src.resource->format) &&
288
			!util_format_is_pure_integer(info.src.resource->format)) {
289
		DBG("color resolve unimplemented");
290
		return;
291
	}
292
 
293
	if (util_try_blit_via_copy_region(pctx, &info)) {
294
		return; /* done */
295
	}
296
 
297
	if (info.mask & PIPE_MASK_S) {
298
		DBG("cannot blit stencil, skipping");
299
		info.mask &= ~PIPE_MASK_S;
300
	}
301
 
302
	render_blit(pctx, &info);
303
}
304
 
305
static bool
306
render_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
307
{
308
	struct fd_context *ctx = fd_context(pctx);
309
 
310
	if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
311
		DBG("blit unsupported %s -> %s",
312
				util_format_short_name(info->src.resource->format),
313
				util_format_short_name(info->dst.resource->format));
314
		return false;
315
	}
316
 
317
	util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertexbuf.vb);
318
	util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx);
319
	util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp);
320
	util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
321
	util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
322
	util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
323
	util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp);
324
	util_blitter_save_blend(ctx->blitter, ctx->blend);
325
	util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
326
	util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
327
	util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
328
	util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
329
	util_blitter_save_fragment_sampler_states(ctx->blitter,
330
			ctx->fragtex.num_samplers,
331
			(void **)ctx->fragtex.samplers);
332
	util_blitter_save_fragment_sampler_views(ctx->blitter,
333
			ctx->fragtex.num_textures, ctx->fragtex.textures);
334
 
335
	util_blitter_blit(ctx->blitter, info);
336
 
337
	return true;
338
}
339
 
340
void
341
fd_resource_screen_init(struct pipe_screen *pscreen)
342
{
343
	pscreen->resource_create = fd_resource_create;
344
	pscreen->resource_from_handle = fd_resource_from_handle;
345
	pscreen->resource_get_handle = u_resource_get_handle_vtbl;
346
	pscreen->resource_destroy = u_resource_destroy_vtbl;
347
}
348
 
349
void
350
fd_resource_context_init(struct pipe_context *pctx)
351
{
352
	pctx->transfer_map = u_transfer_map_vtbl;
353
	pctx->transfer_flush_region = u_transfer_flush_region_vtbl;
354
	pctx->transfer_unmap = u_transfer_unmap_vtbl;
355
	pctx->transfer_inline_write = u_transfer_inline_write_vtbl;
356
	pctx->create_surface = fd_create_surface;
357
	pctx->surface_destroy = fd_surface_destroy;
358
	pctx->resource_copy_region = fd_resource_copy_region;
359
	pctx->blit = fd_blit;
360
}