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