Home | History | Annotate | Download | only in xa
      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