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