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