• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);
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 }
95 
96 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)97 xa_surface_dma(struct xa_context *ctx,
98 	       struct xa_surface *srf,
99 	       void *data,
100 	       unsigned int pitch,
101 	       int to_surface, struct xa_box *boxes, unsigned int num_boxes)
102 {
103     struct pipe_transfer *transfer;
104     void *map;
105     int w, h, i;
106     enum pipe_transfer_usage transfer_direction;
107     struct pipe_context *pipe = ctx->pipe;
108 
109     transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE :
110 			  PIPE_TRANSFER_READ);
111 
112     for (i = 0; i < num_boxes; ++i, ++boxes) {
113 	w = boxes->x2 - boxes->x1;
114 	h = boxes->y2 - boxes->y1;
115 
116 	map = pipe_transfer_map(pipe, srf->tex, 0, 0,
117                                 transfer_direction, boxes->x1, boxes->y1,
118                                 w, h, &transfer);
119 	if (!map)
120 	    return -XA_ERR_NORES;
121 
122 	if (to_surface) {
123 	    util_copy_rect(map, srf->tex->format, transfer->stride,
124 			   0, 0, w, h, data, pitch, boxes->x1, boxes->y1);
125 	} else {
126 	    util_copy_rect(data, srf->tex->format, pitch,
127 			   boxes->x1, boxes->y1, w, h, map, transfer->stride, 0,
128 			   0);
129 	}
130 	pipe->transfer_unmap(pipe, transfer);
131     }
132     return XA_ERR_NONE;
133 }
134 
135 XA_EXPORT void *
xa_surface_map(struct xa_context * ctx,struct xa_surface * srf,unsigned int usage)136 xa_surface_map(struct xa_context *ctx,
137 	       struct xa_surface *srf, unsigned int usage)
138 {
139     void *map;
140     unsigned int gallium_usage = 0;
141     struct pipe_context *pipe = ctx->pipe;
142 
143     /*
144      * A surface may only have a single map.
145      */
146     if (srf->transfer)
147 	return NULL;
148 
149     if (usage & XA_MAP_READ)
150 	gallium_usage |= PIPE_TRANSFER_READ;
151     if (usage & XA_MAP_WRITE)
152 	gallium_usage |= PIPE_TRANSFER_WRITE;
153     if (usage & XA_MAP_MAP_DIRECTLY)
154 	gallium_usage |= PIPE_TRANSFER_MAP_DIRECTLY;
155     if (usage & XA_MAP_UNSYNCHRONIZED)
156 	gallium_usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
157     if (usage & XA_MAP_DONTBLOCK)
158 	gallium_usage |= PIPE_TRANSFER_DONTBLOCK;
159     if (usage & XA_MAP_DISCARD_WHOLE_RESOURCE)
160 	gallium_usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
161 
162     if (!(gallium_usage & (PIPE_TRANSFER_READ_WRITE)))
163 	return NULL;
164 
165     map = pipe_transfer_map(pipe, srf->tex, 0, 0,
166                             gallium_usage, 0, 0,
167                             srf->tex->width0, srf->tex->height0,
168                             &srf->transfer);
169     if (!map)
170 	return NULL;
171 
172     srf->mapping_pipe = pipe;
173     return map;
174 }
175 
176 XA_EXPORT void
xa_surface_unmap(struct xa_surface * srf)177 xa_surface_unmap(struct xa_surface *srf)
178 {
179     if (srf->transfer) {
180 	struct pipe_context *pipe = srf->mapping_pipe;
181 
182 	pipe->transfer_unmap(pipe, srf->transfer);
183 	srf->transfer = NULL;
184     }
185 }
186 
187 int
xa_ctx_srf_create(struct xa_context * ctx,struct xa_surface * dst)188 xa_ctx_srf_create(struct xa_context *ctx, struct xa_surface *dst)
189 {
190     struct pipe_screen *screen = ctx->pipe->screen;
191     struct pipe_surface srf_templ;
192 
193     /*
194      * Cache surfaces unless we change render target
195      */
196     if (ctx->srf) {
197         if (ctx->srf->texture == dst->tex)
198             return XA_ERR_NONE;
199 
200         pipe_surface_reference(&ctx->srf, NULL);
201     }
202 
203     if (!screen->is_format_supported(screen,  dst->tex->format,
204 				     PIPE_TEXTURE_2D, 0,
205 				     PIPE_BIND_RENDER_TARGET))
206 	return -XA_ERR_INVAL;
207 
208     u_surface_default_template(&srf_templ, dst->tex);
209     ctx->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ);
210     if (!ctx->srf)
211 	return -XA_ERR_NORES;
212 
213     return XA_ERR_NONE;
214 }
215 
216 void
xa_ctx_srf_destroy(struct xa_context * ctx)217 xa_ctx_srf_destroy(struct xa_context *ctx)
218 {
219     /*
220      * Cache surfaces unless we change render target.
221      * Final destruction on context destroy.
222      */
223 }
224 
225 XA_EXPORT int
xa_copy_prepare(struct xa_context * ctx,struct xa_surface * dst,struct xa_surface * src)226 xa_copy_prepare(struct xa_context *ctx,
227 		struct xa_surface *dst, struct xa_surface *src)
228 {
229     if (src == dst)
230 	return -XA_ERR_INVAL;
231 
232     if (src->tex->format != dst->tex->format) {
233 	int ret = xa_ctx_srf_create(ctx, dst);
234 	if (ret != XA_ERR_NONE)
235 	    return ret;
236 	renderer_copy_prepare(ctx, ctx->srf, src->tex,
237 			      src->fdesc.xa_format,
238 			      dst->fdesc.xa_format);
239 	ctx->simple_copy = 0;
240     } else
241 	ctx->simple_copy = 1;
242 
243     ctx->src = src;
244     ctx->dst = dst;
245     xa_ctx_srf_destroy(ctx);
246 
247     return 0;
248 }
249 
250 XA_EXPORT void
xa_copy(struct xa_context * ctx,int dx,int dy,int sx,int sy,int width,int height)251 xa_copy(struct xa_context *ctx,
252 	int dx, int dy, int sx, int sy, int width, int height)
253 {
254     struct pipe_box src_box;
255 
256     xa_scissor_update(ctx, dx, dy, dx + width, dy + height);
257 
258     if (ctx->simple_copy) {
259 	u_box_2d(sx, sy, width, height, &src_box);
260 	ctx->pipe->resource_copy_region(ctx->pipe,
261 					ctx->dst->tex, 0, dx, dy, 0,
262 					ctx->src->tex,
263 					0, &src_box);
264     } else
265 	renderer_copy(ctx, dx, dy, sx, sy, width, height,
266 		      (float) ctx->src->tex->width0,
267 		      (float) ctx->src->tex->height0);
268 }
269 
270 XA_EXPORT void
xa_copy_done(struct xa_context * ctx)271 xa_copy_done(struct xa_context *ctx)
272 {
273     if (!ctx->simple_copy) {
274 	renderer_draw_flush(ctx);
275     }
276 }
277 
278 static void
bind_solid_blend_state(struct xa_context * ctx)279 bind_solid_blend_state(struct xa_context *ctx)
280 {
281     struct pipe_blend_state blend;
282 
283     memset(&blend, 0, sizeof(struct pipe_blend_state));
284     blend.rt[0].blend_enable = 0;
285     blend.rt[0].colormask = PIPE_MASK_RGBA;
286 
287     blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
288     blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
289     blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
290     blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
291 
292     cso_set_blend(ctx->cso, &blend);
293 }
294 
295 XA_EXPORT int
xa_solid_prepare(struct xa_context * ctx,struct xa_surface * dst,uint32_t fg)296 xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst,
297 		 uint32_t fg)
298 {
299     unsigned vs_traits, fs_traits;
300     struct xa_shader shader;
301     int ret;
302 
303     ret = xa_ctx_srf_create(ctx, dst);
304     if (ret != XA_ERR_NONE)
305 	return ret;
306 
307     if (ctx->srf->format == PIPE_FORMAT_L8_UNORM)
308 	xa_pixel_to_float4_a8(fg, ctx->solid_color);
309     else
310 	xa_pixel_to_float4(fg, ctx->solid_color);
311     ctx->has_solid_color = 1;
312 
313     ctx->dst = dst;
314 
315 #if 0
316     debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
317 		 (fg >> 24) & 0xff, (fg >> 16) & 0xff,
318 		 (fg >> 8) & 0xff,  (fg >> 0) & 0xff,
319 		 exa->solid_color[0], exa->solid_color[1],
320 		 exa->solid_color[2], exa->solid_color[3]);
321 #endif
322 
323     vs_traits = VS_SOLID_FILL;
324     fs_traits = FS_SOLID_FILL;
325 
326     renderer_bind_destination(ctx, ctx->srf);
327     bind_solid_blend_state(ctx);
328     cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
329     cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
330 
331     shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
332     cso_set_vertex_shader_handle(ctx->cso, shader.vs);
333     cso_set_fragment_shader_handle(ctx->cso, shader.fs);
334 
335     renderer_begin_solid(ctx);
336 
337     xa_ctx_srf_destroy(ctx);
338     return XA_ERR_NONE;
339 }
340 
341 XA_EXPORT void
xa_solid(struct xa_context * ctx,int x,int y,int width,int height)342 xa_solid(struct xa_context *ctx, int x, int y, int width, int height)
343 {
344     xa_scissor_update(ctx, x, y, x + width, y + height);
345     renderer_solid(ctx, x, y, x + width, y + height, ctx->solid_color);
346 }
347 
348 XA_EXPORT void
xa_solid_done(struct xa_context * ctx)349 xa_solid_done(struct xa_context *ctx)
350 {
351     renderer_draw_flush(ctx);
352     ctx->comp = NULL;
353     ctx->has_solid_color = FALSE;
354     ctx->num_bound_samplers = 0;
355 }
356 
357 XA_EXPORT struct xa_fence *
xa_fence_get(struct xa_context * ctx)358 xa_fence_get(struct xa_context *ctx)
359 {
360     struct xa_fence *fence = calloc(1, sizeof(*fence));
361     struct pipe_screen *screen = ctx->xa->screen;
362 
363     if (!fence)
364 	return NULL;
365 
366     fence->xa = ctx->xa;
367 
368     if (ctx->last_fence == NULL)
369 	fence->pipe_fence = NULL;
370     else
371 	screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence);
372 
373     return fence;
374 }
375 
376 XA_EXPORT int
xa_fence_wait(struct xa_fence * fence,uint64_t timeout)377 xa_fence_wait(struct xa_fence *fence, uint64_t timeout)
378 {
379     if (!fence)
380 	return XA_ERR_NONE;
381 
382     if (fence->pipe_fence) {
383 	struct pipe_screen *screen = fence->xa->screen;
384 	boolean timed_out;
385 
386 	timed_out = !screen->fence_finish(screen, NULL, fence->pipe_fence, timeout);
387 	if (timed_out)
388 	    return -XA_ERR_BUSY;
389 
390 	screen->fence_reference(screen, &fence->pipe_fence, NULL);
391     }
392     return XA_ERR_NONE;
393 }
394 
395 XA_EXPORT void
xa_fence_destroy(struct xa_fence * fence)396 xa_fence_destroy(struct xa_fence *fence)
397 {
398     if (!fence)
399 	return;
400 
401     if (fence->pipe_fence) {
402 	struct pipe_screen *screen = fence->xa->screen;
403 
404 	screen->fence_reference(screen, &fence->pipe_fence, NULL);
405     }
406 
407     free(fence);
408 }
409 
410 void
xa_ctx_sampler_views_destroy(struct xa_context * ctx)411 xa_ctx_sampler_views_destroy(struct xa_context *ctx)
412 {
413     int i;
414 
415     for (i = 0; i < ctx->num_bound_samplers; ++i)
416 	pipe_sampler_view_reference(&ctx->bound_sampler_views[i], NULL);
417     ctx->num_bound_samplers = 0;
418 }
419