xa_context.c revision 642951fbcaa56a975422f7caddf6620f20d47721
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 if (r->cso) { 76 cso_release_all(r->cso); 77 cso_destroy_context(r->cso); 78 r->cso = NULL; 79 } 80} 81 82int 83xa_surface_dma(struct xa_context *ctx, 84 struct xa_surface *srf, 85 void *data, 86 unsigned int pitch, 87 int to_surface, struct xa_box *boxes, unsigned int num_boxes) 88{ 89 struct pipe_transfer *transfer; 90 void *map; 91 int w, h, i; 92 enum pipe_transfer_usage transfer_direction; 93 struct pipe_context *pipe = ctx->pipe; 94 95 transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : 96 PIPE_TRANSFER_READ); 97 98 for (i = 0; i < num_boxes; ++i, ++boxes) { 99 w = boxes->x2 - boxes->x1; 100 h = boxes->y2 - boxes->y1; 101 102 transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, 103 transfer_direction, boxes->x1, boxes->y1, 104 w, h); 105 if (!transfer) 106 return -XA_ERR_NORES; 107 108 map = pipe_transfer_map(ctx->pipe, transfer); 109 if (!map) 110 goto out_no_map; 111 112 if (to_surface) { 113 util_copy_rect(map, srf->tex->format, transfer->stride, 114 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); 115 } else { 116 util_copy_rect(data, srf->tex->format, pitch, 117 boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, 118 0); 119 } 120 pipe->transfer_unmap(pipe, transfer); 121 pipe->transfer_destroy(pipe, transfer); 122 if (to_surface) 123 pipe->flush(pipe, &ctx->last_fence); 124 } 125 return XA_ERR_NONE; 126 out_no_map: 127 pipe->transfer_destroy(pipe, transfer); 128 return -XA_ERR_NORES; 129} 130 131void * 132xa_surface_map(struct xa_context *ctx, 133 struct xa_surface *srf, unsigned int usage) 134{ 135 void *map; 136 unsigned int transfer_direction = 0; 137 struct pipe_context *pipe = ctx->pipe; 138 139 if (srf->transfer) 140 return NULL; 141 142 if (usage & XA_MAP_READ) 143 transfer_direction = PIPE_TRANSFER_READ; 144 if (usage & XA_MAP_WRITE) 145 transfer_direction = PIPE_TRANSFER_WRITE; 146 147 if (!transfer_direction) 148 return NULL; 149 150 srf->transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, 151 transfer_direction, 0, 0, 152 srf->tex->width0, srf->tex->height0); 153 if (!srf->transfer) 154 return NULL; 155 156 map = pipe_transfer_map(pipe, srf->transfer); 157 if (!map) 158 pipe->transfer_destroy(pipe, srf->transfer); 159 160 srf->mapping_pipe = pipe; 161 return map; 162} 163 164void 165xa_surface_unmap(struct xa_surface *srf) 166{ 167 if (srf->transfer) { 168 struct pipe_context *pipe = srf->mapping_pipe; 169 170 pipe->transfer_unmap(pipe, srf->transfer); 171 pipe->transfer_destroy(pipe, srf->transfer); 172 srf->transfer = NULL; 173 } 174} 175 176int 177xa_copy_prepare(struct xa_context *ctx, 178 struct xa_surface *dst, struct xa_surface *src) 179{ 180 if (src == dst || dst->srf != NULL) 181 return -XA_ERR_INVAL; 182 183 if (src->tex->format != dst->tex->format) { 184 struct pipe_screen *screen = ctx->pipe->screen; 185 struct pipe_surface srf_templ; 186 187 if (!screen->is_format_supported(screen, dst->tex->format, 188 PIPE_TEXTURE_2D, 0, 189 PIPE_BIND_RENDER_TARGET)) 190 return -XA_ERR_INVAL; 191 u_surface_default_template(&srf_templ, dst->tex, 192 PIPE_BIND_RENDER_TARGET); 193 dst->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ); 194 if (!dst->srf) 195 return -XA_ERR_NORES; 196 197 renderer_copy_prepare(ctx, dst->srf, src->tex); 198 ctx->simple_copy = 0; 199 } else 200 ctx->simple_copy = 1; 201 202 ctx->src = src; 203 ctx->dst = dst; 204 205 return 0; 206} 207 208void 209xa_copy(struct xa_context *ctx, 210 int dx, int dy, int sx, int sy, int width, int height) 211{ 212 struct pipe_box src_box; 213 214 if (ctx->simple_copy) { 215 u_box_2d(sx, sy, width, height, &src_box); 216 ctx->pipe->resource_copy_region(ctx->pipe, 217 ctx->dst->tex, 0, dx, dy, 0, 218 ctx->src->tex, 219 0, &src_box); 220 } else 221 renderer_copy(ctx, dx, dy, sx, sy, width, height, 222 (float) width, (float) height); 223} 224 225void 226xa_copy_done(struct xa_context *ctx) 227{ 228 if (!ctx->simple_copy) { 229 renderer_draw_flush(ctx); 230 ctx->pipe->flush(ctx->pipe, &ctx->last_fence); 231 pipe_surface_reference(&ctx->dst->srf, NULL); 232 } else 233 ctx->pipe->flush(ctx->pipe, &ctx->last_fence); 234} 235 236struct xa_fence * 237xa_fence_get(struct xa_context *ctx) 238{ 239 struct xa_fence *fence = malloc(sizeof(*fence)); 240 struct pipe_screen *screen = ctx->xa->screen; 241 242 if (!fence) 243 return NULL; 244 245 fence->xa = ctx->xa; 246 247 if (ctx->last_fence == NULL) 248 fence->pipe_fence = NULL; 249 else 250 screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence); 251 252 return fence; 253} 254 255int 256xa_fence_wait(struct xa_fence *fence, uint64_t timeout) 257{ 258 if (!fence) 259 return XA_ERR_NONE; 260 261 if (fence->pipe_fence) { 262 struct pipe_screen *screen = fence->xa->screen; 263 boolean timed_out; 264 265 timed_out = !screen->fence_finish(screen, fence->pipe_fence, timeout); 266 if (timed_out) 267 return -XA_ERR_BUSY; 268 269 screen->fence_reference(screen, &fence->pipe_fence, NULL); 270 } 271 return XA_ERR_NONE; 272} 273 274void 275xa_fence_destroy(struct xa_fence *fence) 276{ 277 if (!fence) 278 return; 279 280 if (fence->pipe_fence) { 281 struct pipe_screen *screen = fence->xa->screen; 282 283 screen->fence_reference(screen, &fence->pipe_fence, NULL); 284 } 285 286 free(fence); 287} 288