1 /**********************************************************
2  * Copyright 2009-2011 VMware, Inc. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  *********************************************************
25  * Authors:
26  * Zack Rusin <zackr-at-vmware-dot-com>
27  * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
28  */
29 #include "xa_context.h"
30 #include "xa_priv.h"
31 #include "cso_cache/cso_context.h"
32 #include "util/u_inlines.h"
33 #include "util/u_rect.h"
34 #include "util/u_surface.h"
35 #include "pipe/p_context.h"
36 
37 XA_EXPORT void
xa_context_flush(struct xa_context * ctx)38 xa_context_flush(struct xa_context *ctx)
39 {
40     if (ctx->last_fence) {
41         struct pipe_screen *screen = ctx->xa->screen;
42         screen->fence_reference(screen, &ctx->last_fence, NULL);
43     }
44     ctx->pipe->flush(ctx->pipe, &ctx->last_fence, 0);
45 }
46 
47 XA_EXPORT struct xa_context *
xa_context_default(struct xa_tracker * xa)48 xa_context_default(struct xa_tracker *xa)
49 {
50     return xa->default_ctx;
51 }
52 
53 XA_EXPORT struct xa_context *
xa_context_create(struct xa_tracker * xa)54 xa_context_create(struct xa_tracker *xa)
55 {
56     struct xa_context *ctx = calloc(1, sizeof(*ctx));
57 
58     ctx->xa = xa;
59     ctx->pipe = xa->screen->context_create(xa->screen, NULL, 0);
60     ctx->cso = cso_create_context(ctx->pipe, 0);
61     ctx->shaders = xa_shaders_create(ctx);
62     renderer_init_state(ctx);
63 
64     return ctx;
65 }
66 
67 XA_EXPORT void
xa_context_destroy(struct xa_context * r)68 xa_context_destroy(struct xa_context *r)
69 {
70     struct pipe_resource **vsbuf = &r->vs_const_buffer;
71     struct pipe_resource **fsbuf = &r->fs_const_buffer;
72 
73     if (*vsbuf)
74 	pipe_resource_reference(vsbuf, NULL);
75 
76     if (*fsbuf)
77 	pipe_resource_reference(fsbuf, NULL);
78 
79     if (r->shaders) {
80 	xa_shaders_destroy(r->shaders);
81 	r->shaders = NULL;
82     }
83 
84     xa_ctx_sampler_views_destroy(r);
85     if (r->srf)
86         pipe_surface_reference(&r->srf, NULL);
87 
88     if (r->cso) {
89 	cso_destroy_context(r->cso);
90 	r->cso = NULL;
91     }
92 
93     r->pipe->destroy(r->pipe);
94     free(r);
95 }
96 
97 XA_EXPORT int
xa_surface_dma(struct xa_context * ctx,struct xa_surface * srf,void * data,unsigned int pitch,int to_surface,struct xa_box * boxes,unsigned int num_boxes)98 xa_surface_dma(struct xa_context *ctx,
99 	       struct xa_surface *srf,
100 	       void *data,
101 	       unsigned int pitch,
102 	       int to_surface, struct xa_box *boxes, unsigned int num_boxes)
103 {
104     struct pipe_transfer *transfer;
105     void *map;
106     int w, h, i;
107     enum pipe_map_flags transfer_direction;
108     struct pipe_context *pipe = ctx->pipe;
109 
110     transfer_direction = (to_surface ? PIPE_MAP_WRITE :
111 			  PIPE_MAP_READ);
112 
113     for (i = 0; i < num_boxes; ++i, ++boxes) {
114 	w = boxes->x2 - boxes->x1;
115 	h = boxes->y2 - boxes->y1;
116 
117 	map = pipe_texture_map(pipe, srf->tex, 0, 0,
118                                 transfer_direction, boxes->x1, boxes->y1,
119                                 w, h, &transfer);
120 	if (!map)
121 	    return -XA_ERR_NORES;
122 
123 	if (to_surface) {
124 	    util_copy_rect(map, srf->tex->format, transfer->stride,
125 			   0, 0, w, h, data, pitch, boxes->x1, boxes->y1);
126 	} else {
127 	    util_copy_rect(data, srf->tex->format, pitch,
128 			   boxes->x1, boxes->y1, w, h, map, transfer->stride, 0,
129 			   0);
130 	}
131 	pipe->texture_unmap(pipe, transfer);
132     }
133     return XA_ERR_NONE;
134 }
135 
136 XA_EXPORT void *
xa_surface_map(struct xa_context * ctx,struct xa_surface * srf,unsigned int usage)137 xa_surface_map(struct xa_context *ctx,
138 	       struct xa_surface *srf, unsigned int usage)
139 {
140     void *map;
141     unsigned int gallium_usage = 0;
142     struct pipe_context *pipe = ctx->pipe;
143 
144     /*
145      * A surface may only have a single map.
146      */
147     if (srf->transfer)
148 	return NULL;
149 
150     if (usage & XA_MAP_READ)
151 	gallium_usage |= PIPE_MAP_READ;
152     if (usage & XA_MAP_WRITE)
153 	gallium_usage |= PIPE_MAP_WRITE;
154     if (usage & XA_MAP_MAP_DIRECTLY)
155 	gallium_usage |= PIPE_MAP_DIRECTLY;
156     if (usage & XA_MAP_UNSYNCHRONIZED)
157 	gallium_usage |= PIPE_MAP_UNSYNCHRONIZED;
158     if (usage & XA_MAP_DONTBLOCK)
159 	gallium_usage |= PIPE_MAP_DONTBLOCK;
160     if (usage & XA_MAP_DISCARD_WHOLE_RESOURCE)
161 	gallium_usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE;
162 
163     if (!(gallium_usage & (PIPE_MAP_READ_WRITE)))
164 	return NULL;
165 
166     map = pipe_texture_map(pipe, srf->tex, 0, 0,
167                             gallium_usage, 0, 0,
168                             srf->tex->width0, srf->tex->height0,
169                             &srf->transfer);
170     if (!map)
171 	return NULL;
172 
173     srf->mapping_pipe = pipe;
174     return map;
175 }
176 
177 XA_EXPORT void
xa_surface_unmap(struct xa_surface * srf)178 xa_surface_unmap(struct xa_surface *srf)
179 {
180     if (srf->transfer) {
181 	struct pipe_context *pipe = srf->mapping_pipe;
182 
183 	pipe->texture_unmap(pipe, srf->transfer);
184 	srf->transfer = NULL;
185     }
186 }
187 
188 int
xa_ctx_srf_create(struct xa_context * ctx,struct xa_surface * dst)189 xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst)
190 {
191     struct pipe_screen *screen = ctx->pipe->screen;
192     struct pipe_surface srf_templ;
193 
194     /*
195      * Cache surfaces unless we change render target
196      */
197     if (ctx->srf) {
198         if (ctx->srf->texture == dst->tex)
199             return XA_ERR_NONE;
200 
201         pipe_surface_reference(&ctx->srf, NULL);
202     }
203 
204     if (!screen->is_format_supported(screen,  dst->tex->format,
205 				     PIPE_TEXTURE_2D, 0, 0,
206 				     PIPE_BIND_RENDER_TARGET))
207 	return -XA_ERR_INVAL;
208 
209     u_surface_default_template(&srf_templ, dst->tex);
210     ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ);
211     if (!ctx->srf)
212 	return -XA_ERR_NORES;
213 
214     return XA_ERR_NONE;
215 }
216 
217 void
xa_ctx_srf_destroy(struct xa_context * ctx)218 xa_ctx_srf_destroy(struct xa_context *ctx)
219 {
220     /*
221      * Cache surfaces unless we change render target.
222      * Final destruction on context destroy.
223      */
224 }
225 
226 XA_EXPORT int
xa_copy_prepare(struct xa_context * ctx,struct xa_surface * dst,struct xa_surface * src)227 xa_copy_prepare(struct xa_context *ctx,
228 		struct xa_surface *dst, struct xa_surface *src)
229 {
230     if (src == dst)
231 	return -XA_ERR_INVAL;
232 
233     if (src->tex->format != dst->tex->format) {
234 	int ret = xa_ctx_srf_create(ctx, dst);
235 	if (ret != XA_ERR_NONE)
236 	    return ret;
237 	renderer_copy_prepare(ctx, ctx->srf, src->tex,
238 			      src->fdesc.xa_format,
239 			      dst->fdesc.xa_format);
240 	ctx->simple_copy = 0;
241     } else
242 	ctx->simple_copy = 1;
243 
244     ctx->src = src;
245     ctx->dst = dst;
246     xa_ctx_srf_destroy(ctx);
247 
248     return 0;
249 }
250 
251 XA_EXPORT void
xa_copy(struct xa_context * ctx,int dx,int dy,int sx,int sy,int width,int height)252 xa_copy(struct xa_context *ctx,
253 	int dx, int dy, int sx, int sy, int width, int height)
254 {
255     struct pipe_box src_box;
256 
257     xa_scissor_update(ctx, dx, dy, dx + width, dy + height);
258 
259     if (ctx->simple_copy) {
260 	u_box_2d(sx, sy, width, height, &src_box);
261 	ctx->pipe->resource_copy_region(ctx->pipe,
262 					ctx->dst->tex, 0, dx, dy, 0,
263 					ctx->src->tex,
264 					0, &src_box);
265     } else
266 	renderer_copy(ctx, dx, dy, sx, sy, width, height,
267 		      (float) ctx->src->tex->width0,
268 		      (float) ctx->src->tex->height0);
269 }
270 
271 XA_EXPORT void
xa_copy_done(struct xa_context * ctx)272 xa_copy_done(struct xa_context *ctx)
273 {
274     if (!ctx->simple_copy) {
275 	renderer_draw_flush(ctx);
276     }
277 }
278 
279 static void
bind_solid_blend_state(struct xa_context * ctx)280 bind_solid_blend_state(struct xa_context *ctx)
281 {
282     struct pipe_blend_state blend;
283 
284     memset(&blend, 0, sizeof(struct pipe_blend_state));
285     blend.rt[0].blend_enable = 0;
286     blend.rt[0].colormask = PIPE_MASK_RGBA;
287 
288     blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
289     blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
290     blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
291     blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
292 
293     cso_set_blend(ctx->cso, &blend);
294 }
295 
296 XA_EXPORT int
xa_solid_prepare(struct xa_context * ctx,struct xa_surface * dst,uint32_t fg)297 xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst,
298 		 uint32_t fg)
299 {
300     unsigned vs_traits, fs_traits;
301     struct xa_shader shader;
302     int ret;
303 
304     ret = xa_ctx_srf_create(ctx, dst);
305     if (ret != XA_ERR_NONE)
306 	return ret;
307 
308     if (ctx->srf->format == PIPE_FORMAT_L8_UNORM)
309 	xa_pixel_to_float4_a8(fg, ctx->solid_color);
310     else
311 	xa_pixel_to_float4(fg, ctx->solid_color);
312     ctx->has_solid_src = 1;
313 
314     ctx->dst = dst;
315 
316 #if 0
317     debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
318 		 (fg >> 24) & 0xff, (fg >> 16) & 0xff,
319 		 (fg >> 8) & 0xff,  (fg >> 0) & 0xff,
320 		 exa->solid_color[0], exa->solid_color[1],
321 		 exa->solid_color[2], exa->solid_color[3]);
322 #endif
323 
324     vs_traits = VS_SRC_SRC | VS_COMPOSITE;
325     fs_traits = FS_SRC_SRC | VS_COMPOSITE;
326 
327     renderer_bind_destination(ctx, ctx->srf);
328     bind_solid_blend_state(ctx);
329     cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
330     ctx->pipe->set_sampler_views(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, 0,
331                                  XA_MAX_SAMPLERS, false, NULL);
332 
333     shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
334     cso_set_vertex_shader_handle(ctx->cso, shader.vs);
335     cso_set_fragment_shader_handle(ctx->cso, shader.fs);
336 
337     renderer_begin_solid(ctx);
338 
339     xa_ctx_srf_destroy(ctx);
340     return XA_ERR_NONE;
341 }
342 
343 XA_EXPORT void
xa_solid(struct xa_context * ctx,int x,int y,int width,int height)344 xa_solid(struct xa_context *ctx, int x, int y, int width, int height)
345 {
346     xa_scissor_update(ctx, x, y, x + width, y + height);
347     renderer_solid(ctx, x, y, x + width, y + height);
348 }
349 
350 XA_EXPORT void
xa_solid_done(struct xa_context * ctx)351 xa_solid_done(struct xa_context *ctx)
352 {
353     renderer_draw_flush(ctx);
354     ctx->comp = NULL;
355     ctx->has_solid_src = FALSE;
356     ctx->num_bound_samplers = 0;
357 }
358 
359 XA_EXPORT struct xa_fence *
xa_fence_get(struct xa_context * ctx)360 xa_fence_get(struct xa_context *ctx)
361 {
362     struct xa_fence *fence = calloc(1, sizeof(*fence));
363     struct pipe_screen *screen = ctx->xa->screen;
364 
365     if (!fence)
366 	return NULL;
367 
368     fence->xa = ctx->xa;
369 
370     if (ctx->last_fence == NULL)
371 	fence->pipe_fence = NULL;
372     else
373 	screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence);
374 
375     return fence;
376 }
377 
378 XA_EXPORT int
xa_fence_wait(struct xa_fence * fence,uint64_t timeout)379 xa_fence_wait(struct xa_fence *fence, uint64_t timeout)
380 {
381     if (!fence)
382 	return XA_ERR_NONE;
383 
384     if (fence->pipe_fence) {
385 	struct pipe_screen *screen = fence->xa->screen;
386 	boolean timed_out;
387 
388 	timed_out = !screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
389 	if (timed_out)
390 	    return -XA_ERR_BUSY;
391 
392 	screen->fence_reference(screen, &fence->pipe_fence, NULL);
393     }
394     return XA_ERR_NONE;
395 }
396 
397 XA_EXPORT void
xa_fence_destroy(struct xa_fence * fence)398 xa_fence_destroy(struct xa_fence *fence)
399 {
400     if (!fence)
401 	return;
402 
403     if (fence->pipe_fence) {
404 	struct pipe_screen *screen = fence->xa->screen;
405 
406 	screen->fence_reference(screen, &fence->pipe_fence, NULL);
407     }
408 
409     free(fence);
410 }
411 
412 void
xa_ctx_sampler_views_destroy(struct xa_context * ctx)413 xa_ctx_sampler_views_destroy(struct xa_context *ctx)
414 {
415     int i;
416 
417     for (i = 0; i < ctx->num_bound_samplers; ++i)
418 	pipe_sampler_view_reference(&ctx->bound_sampler_views[i], NULL);
419     ctx->num_bound_samplers = 0;
420 }
421