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 37XA_EXPORT void 38xa_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 47XA_EXPORT struct xa_context * 48xa_context_default(struct xa_tracker *xa) 49{ 50 return xa->default_ctx; 51} 52 53XA_EXPORT struct xa_context * 54xa_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 67XA_EXPORT void 68xa_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 97XA_EXPORT int 98xa_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 136XA_EXPORT void * 137xa_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 177XA_EXPORT void 178xa_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 188int 189xa_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 217void 218xa_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 226XA_EXPORT int 227xa_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 251XA_EXPORT void 252xa_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 271XA_EXPORT void 272xa_copy_done(struct xa_context *ctx) 273{ 274 if (!ctx->simple_copy) { 275 renderer_draw_flush(ctx); 276 } 277} 278 279static void 280bind_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 296XA_EXPORT int 297xa_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 343XA_EXPORT void 344xa_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 350XA_EXPORT void 351xa_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 359XA_EXPORT struct xa_fence * 360xa_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 378XA_EXPORT int 379xa_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 397XA_EXPORT void 398xa_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 412void 413xa_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