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