Home | History | Annotate | Download | only in vdpau
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 Thomas Balling Srensen.
      4  * Copyright 2011 Christian Knig.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sub license, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial portions
     17  * of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  **************************************************************************/
     28 
     29 #include <vdpau/vdpau.h>
     30 
     31 #include "util/u_debug.h"
     32 #include "util/u_memory.h"
     33 #include "util/u_sampler.h"
     34 #include "util/u_format.h"
     35 
     36 #include "vl/vl_csc.h"
     37 
     38 #include "vdpau_private.h"
     39 
     40 /**
     41  * Create a VdpOutputSurface.
     42  */
     43 VdpStatus
     44 vlVdpOutputSurfaceCreate(VdpDevice device,
     45                          VdpRGBAFormat rgba_format,
     46                          uint32_t width, uint32_t height,
     47                          VdpOutputSurface  *surface)
     48 {
     49    struct pipe_context *pipe;
     50    struct pipe_resource res_tmpl, *res;
     51    struct pipe_sampler_view sv_templ;
     52    struct pipe_surface surf_templ;
     53 
     54    vlVdpOutputSurface *vlsurface = NULL;
     55 
     56    if (!(width && height))
     57       return VDP_STATUS_INVALID_SIZE;
     58 
     59    vlVdpDevice *dev = vlGetDataHTAB(device);
     60    if (!dev)
     61       return VDP_STATUS_INVALID_HANDLE;
     62 
     63    pipe = dev->context;
     64    if (!pipe)
     65       return VDP_STATUS_INVALID_HANDLE;
     66 
     67    vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface));
     68    if (!vlsurface)
     69       return VDP_STATUS_RESOURCES;
     70 
     71    vlsurface->device = dev;
     72 
     73    memset(&res_tmpl, 0, sizeof(res_tmpl));
     74 
     75    res_tmpl.target = PIPE_TEXTURE_2D;
     76    res_tmpl.format = FormatRGBAToPipe(rgba_format);
     77    res_tmpl.width0 = width;
     78    res_tmpl.height0 = height;
     79    res_tmpl.depth0 = 1;
     80    res_tmpl.array_size = 1;
     81    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
     82    res_tmpl.usage = PIPE_USAGE_STATIC;
     83 
     84    pipe_mutex_lock(dev->mutex);
     85    res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
     86    if (!res) {
     87       pipe_mutex_unlock(dev->mutex);
     88       FREE(dev);
     89       return VDP_STATUS_ERROR;
     90    }
     91 
     92    vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
     93    vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
     94    if (!vlsurface->sampler_view) {
     95       pipe_resource_reference(&res, NULL);
     96       pipe_mutex_unlock(dev->mutex);
     97       FREE(dev);
     98       return VDP_STATUS_ERROR;
     99    }
    100 
    101    memset(&surf_templ, 0, sizeof(surf_templ));
    102    surf_templ.format = res->format;
    103    surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
    104    vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
    105    if (!vlsurface->surface) {
    106       pipe_resource_reference(&res, NULL);
    107       pipe_mutex_unlock(dev->mutex);
    108       FREE(dev);
    109       return VDP_STATUS_ERROR;
    110    }
    111 
    112    *surface = vlAddDataHTAB(vlsurface);
    113    if (*surface == 0) {
    114       pipe_resource_reference(&res, NULL);
    115       pipe_mutex_unlock(dev->mutex);
    116       FREE(dev);
    117       return VDP_STATUS_ERROR;
    118    }
    119 
    120    pipe_resource_reference(&res, NULL);
    121 
    122    vl_compositor_init_state(&vlsurface->cstate, pipe);
    123    vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
    124    pipe_mutex_unlock(dev->mutex);
    125 
    126    return VDP_STATUS_OK;
    127 }
    128 
    129 /**
    130  * Destroy a VdpOutputSurface.
    131  */
    132 VdpStatus
    133 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
    134 {
    135    vlVdpOutputSurface *vlsurface;
    136    struct pipe_context *pipe;
    137 
    138    vlsurface = vlGetDataHTAB(surface);
    139    if (!vlsurface)
    140       return VDP_STATUS_INVALID_HANDLE;
    141 
    142    pipe = vlsurface->device->context;
    143 
    144    pipe_mutex_lock(vlsurface->device->mutex);
    145    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
    146 
    147    pipe_surface_reference(&vlsurface->surface, NULL);
    148    pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
    149    pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL);
    150    vl_compositor_cleanup_state(&vlsurface->cstate);
    151    pipe_mutex_unlock(vlsurface->device->mutex);
    152 
    153    vlRemoveDataHTAB(surface);
    154    FREE(vlsurface);
    155 
    156    return VDP_STATUS_OK;
    157 }
    158 
    159 /**
    160  * Retrieve the parameters used to create a VdpOutputSurface.
    161  */
    162 VdpStatus
    163 vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
    164                                 VdpRGBAFormat *rgba_format,
    165                                 uint32_t *width, uint32_t *height)
    166 {
    167    vlVdpOutputSurface *vlsurface;
    168 
    169    vlsurface = vlGetDataHTAB(surface);
    170    if (!vlsurface)
    171       return VDP_STATUS_INVALID_HANDLE;
    172 
    173    *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
    174    *width = vlsurface->sampler_view->texture->width0;
    175    *height = vlsurface->sampler_view->texture->height0;
    176 
    177    return VDP_STATUS_OK;
    178 }
    179 
    180 /**
    181  * Copy image data from a VdpOutputSurface to application memory in the
    182  * surface's native format.
    183  */
    184 VdpStatus
    185 vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
    186                                 VdpRect const *source_rect,
    187                                 void *const *destination_data,
    188                                 uint32_t const *destination_pitches)
    189 {
    190    vlVdpOutputSurface *vlsurface;
    191    struct pipe_context *pipe;
    192    struct pipe_resource *res;
    193    struct pipe_box box;
    194    struct pipe_transfer *transfer;
    195    uint8_t *map;
    196 
    197    vlsurface = vlGetDataHTAB(surface);
    198    if (!vlsurface)
    199       return VDP_STATUS_INVALID_HANDLE;
    200 
    201    pipe = vlsurface->device->context;
    202    if (!pipe)
    203       return VDP_STATUS_INVALID_HANDLE;
    204 
    205    pipe_mutex_lock(vlsurface->device->mutex);
    206    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
    207 
    208    res = vlsurface->sampler_view->texture;
    209    box = RectToPipeBox(source_rect, res);
    210    transfer = pipe->get_transfer(pipe, res, 0, PIPE_TRANSFER_READ, &box);
    211    if (transfer == NULL) {
    212       pipe_mutex_unlock(vlsurface->device->mutex);
    213       return VDP_STATUS_RESOURCES;
    214    }
    215 
    216    map = pipe_transfer_map(pipe, transfer);
    217    if (map == NULL) {
    218       pipe_transfer_destroy(pipe, transfer);
    219       pipe_mutex_unlock(vlsurface->device->mutex);
    220       return VDP_STATUS_RESOURCES;
    221    }
    222 
    223    util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
    224                   box.width, box.height, map, transfer->stride, 0, 0);
    225 
    226    pipe_transfer_unmap(pipe, transfer);
    227    pipe_transfer_destroy(pipe, transfer);
    228    pipe_mutex_unlock(vlsurface->device->mutex);
    229 
    230    return VDP_STATUS_OK;
    231 }
    232 
    233 /**
    234  * Copy image data from application memory in the surface's native format to
    235  * a VdpOutputSurface.
    236  */
    237 VdpStatus
    238 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
    239                                 void const *const *source_data,
    240                                 uint32_t const *source_pitches,
    241                                 VdpRect const *destination_rect)
    242 {
    243    vlVdpOutputSurface *vlsurface;
    244    struct pipe_box dst_box;
    245    struct pipe_context *pipe;
    246 
    247    vlsurface = vlGetDataHTAB(surface);
    248    if (!vlsurface)
    249       return VDP_STATUS_INVALID_HANDLE;
    250 
    251    pipe = vlsurface->device->context;
    252    if (!pipe)
    253       return VDP_STATUS_INVALID_HANDLE;
    254 
    255    pipe_mutex_lock(vlsurface->device->mutex);
    256    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
    257 
    258    dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
    259    pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
    260                                PIPE_TRANSFER_WRITE, &dst_box, *source_data,
    261                                *source_pitches, 0);
    262    pipe_mutex_unlock(vlsurface->device->mutex);
    263 
    264    return VDP_STATUS_OK;
    265 }
    266 
    267 /**
    268  * Copy image data from application memory in a specific indexed format to
    269  * a VdpOutputSurface.
    270  */
    271 VdpStatus
    272 vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
    273                                  VdpIndexedFormat source_indexed_format,
    274                                  void const *const *source_data,
    275                                  uint32_t const *source_pitch,
    276                                  VdpRect const *destination_rect,
    277                                  VdpColorTableFormat color_table_format,
    278                                  void const *color_table)
    279 {
    280    vlVdpOutputSurface *vlsurface;
    281    struct pipe_context *context;
    282    struct vl_compositor *compositor;
    283    struct vl_compositor_state *cstate;
    284 
    285    enum pipe_format index_format;
    286    enum pipe_format colortbl_format;
    287 
    288    struct pipe_resource *res, res_tmpl;
    289    struct pipe_sampler_view sv_tmpl;
    290    struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
    291 
    292    struct pipe_box box;
    293    struct u_rect dst_rect;
    294 
    295    vlsurface = vlGetDataHTAB(surface);
    296    if (!vlsurface)
    297       return VDP_STATUS_INVALID_HANDLE;
    298 
    299    context = vlsurface->device->context;
    300    compositor = &vlsurface->device->compositor;
    301    cstate = &vlsurface->cstate;
    302 
    303    index_format = FormatIndexedToPipe(source_indexed_format);
    304    if (index_format == PIPE_FORMAT_NONE)
    305        return VDP_STATUS_INVALID_INDEXED_FORMAT;
    306 
    307    if (!source_data || !source_pitch)
    308        return VDP_STATUS_INVALID_POINTER;
    309 
    310    colortbl_format = FormatColorTableToPipe(color_table_format);
    311    if (colortbl_format == PIPE_FORMAT_NONE)
    312        return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
    313 
    314    if (!color_table)
    315        return VDP_STATUS_INVALID_POINTER;
    316 
    317    memset(&res_tmpl, 0, sizeof(res_tmpl));
    318    res_tmpl.target = PIPE_TEXTURE_2D;
    319    res_tmpl.format = index_format;
    320 
    321    if (destination_rect) {
    322       res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
    323       res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
    324    } else {
    325       res_tmpl.width0 = vlsurface->surface->texture->width0;
    326       res_tmpl.height0 = vlsurface->surface->texture->height0;
    327    }
    328    res_tmpl.depth0 = 1;
    329    res_tmpl.array_size = 1;
    330    res_tmpl.usage = PIPE_USAGE_STAGING;
    331    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
    332 
    333    pipe_mutex_lock(vlsurface->device->mutex);
    334    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
    335 
    336    res = context->screen->resource_create(context->screen, &res_tmpl);
    337    if (!res)
    338       goto error_resource;
    339 
    340    box.x = box.y = box.z = 0;
    341    box.width = res->width0;
    342    box.height = res->height0;
    343    box.depth = res->depth0;
    344 
    345    context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
    346                                   source_data[0], source_pitch[0],
    347                                   source_pitch[0] * res->height0);
    348 
    349    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
    350    u_sampler_view_default_template(&sv_tmpl, res, res->format);
    351 
    352    sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
    353    pipe_resource_reference(&res, NULL);
    354 
    355    if (!sv_idx)
    356       goto error_resource;
    357 
    358    memset(&res_tmpl, 0, sizeof(res_tmpl));
    359    res_tmpl.target = PIPE_TEXTURE_1D;
    360    res_tmpl.format = colortbl_format;
    361    res_tmpl.width0 = 1 << util_format_get_component_bits(
    362       index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
    363    res_tmpl.height0 = 1;
    364    res_tmpl.depth0 = 1;
    365    res_tmpl.array_size = 1;
    366    res_tmpl.usage = PIPE_USAGE_STAGING;
    367    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
    368 
    369    res = context->screen->resource_create(context->screen, &res_tmpl);
    370    if (!res)
    371       goto error_resource;
    372 
    373    box.x = box.y = box.z = 0;
    374    box.width = res->width0;
    375    box.height = res->height0;
    376    box.depth = res->depth0;
    377 
    378    context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
    379                                   util_format_get_stride(colortbl_format, res->width0), 0);
    380 
    381    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
    382    u_sampler_view_default_template(&sv_tmpl, res, res->format);
    383 
    384    sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
    385    pipe_resource_reference(&res, NULL);
    386 
    387    if (!sv_tbl)
    388       goto error_resource;
    389 
    390    vl_compositor_clear_layers(cstate);
    391    vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
    392    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
    393    vl_compositor_render(cstate, compositor, vlsurface->surface, NULL);
    394 
    395    pipe_sampler_view_reference(&sv_idx, NULL);
    396    pipe_sampler_view_reference(&sv_tbl, NULL);
    397    pipe_mutex_unlock(vlsurface->device->mutex);
    398 
    399    return VDP_STATUS_OK;
    400 
    401 error_resource:
    402    pipe_sampler_view_reference(&sv_idx, NULL);
    403    pipe_sampler_view_reference(&sv_tbl, NULL);
    404    pipe_mutex_unlock(vlsurface->device->mutex);
    405    return VDP_STATUS_RESOURCES;
    406 }
    407 
    408 /**
    409  * Copy image data from application memory in a specific YCbCr format to
    410  * a VdpOutputSurface.
    411  */
    412 VdpStatus
    413 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
    414                                VdpYCbCrFormat source_ycbcr_format,
    415                                void const *const *source_data,
    416                                uint32_t const *source_pitches,
    417                                VdpRect const *destination_rect,
    418                                VdpCSCMatrix const *csc_matrix)
    419 {
    420    vlVdpOutputSurface *vlsurface;
    421    struct vl_compositor *compositor;
    422    struct vl_compositor_state *cstate;
    423 
    424    struct pipe_context *pipe;
    425    enum pipe_format format;
    426    struct pipe_video_buffer vtmpl, *vbuffer;
    427    struct u_rect dst_rect;
    428    struct pipe_sampler_view **sampler_views;
    429 
    430    unsigned i;
    431 
    432    vlsurface = vlGetDataHTAB(surface);
    433    if (!vlsurface)
    434       return VDP_STATUS_INVALID_HANDLE;
    435 
    436 
    437    pipe = vlsurface->device->context;
    438    compositor = &vlsurface->device->compositor;
    439    cstate = &vlsurface->cstate;
    440 
    441    format = FormatYCBCRToPipe(source_ycbcr_format);
    442    if (format == PIPE_FORMAT_NONE)
    443        return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
    444 
    445    if (!source_data || !source_pitches)
    446        return VDP_STATUS_INVALID_POINTER;
    447 
    448    pipe_mutex_lock(vlsurface->device->mutex);
    449    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
    450    memset(&vtmpl, 0, sizeof(vtmpl));
    451    vtmpl.buffer_format = format;
    452    vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
    453 
    454    if (destination_rect) {
    455       vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
    456       vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
    457    } else {
    458       vtmpl.width = vlsurface->surface->texture->width0;
    459       vtmpl.height = vlsurface->surface->texture->height0;
    460    }
    461 
    462    vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
    463    if (!vbuffer) {
    464       pipe_mutex_unlock(vlsurface->device->mutex);
    465       return VDP_STATUS_RESOURCES;
    466    }
    467 
    468    sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
    469    if (!sampler_views) {
    470       vbuffer->destroy(vbuffer);
    471       pipe_mutex_unlock(vlsurface->device->mutex);
    472       return VDP_STATUS_RESOURCES;
    473    }
    474 
    475    for (i = 0; i < 3; ++i) {
    476       struct pipe_sampler_view *sv = sampler_views[i];
    477       if (!sv) continue;
    478 
    479       struct pipe_box dst_box = {
    480          0, 0, 0,
    481          sv->texture->width0, sv->texture->height0, 1
    482       };
    483 
    484       pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
    485                                   source_data[i], source_pitches[i], 0);
    486    }
    487 
    488    if (!csc_matrix) {
    489       vl_csc_matrix csc;
    490       vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
    491       vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
    492    } else {
    493       vl_compositor_set_csc_matrix(cstate, csc_matrix);
    494    }
    495 
    496    vl_compositor_clear_layers(cstate);
    497    vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
    498    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
    499    vl_compositor_render(cstate, compositor, vlsurface->surface, NULL);
    500 
    501    vbuffer->destroy(vbuffer);
    502    pipe_mutex_unlock(vlsurface->device->mutex);
    503 
    504    return VDP_STATUS_OK;
    505 }
    506 
    507 static unsigned
    508 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
    509 {
    510    switch (factor) {
    511    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
    512       return PIPE_BLENDFACTOR_ZERO;
    513    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
    514       return PIPE_BLENDFACTOR_ONE;
    515    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
    516       return PIPE_BLENDFACTOR_SRC_COLOR;
    517    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
    518       return PIPE_BLENDFACTOR_INV_SRC_COLOR;
    519    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
    520       return PIPE_BLENDFACTOR_SRC_ALPHA;
    521    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
    522       return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
    523    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
    524       return PIPE_BLENDFACTOR_DST_ALPHA;
    525    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
    526       return PIPE_BLENDFACTOR_INV_DST_ALPHA;
    527    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
    528       return PIPE_BLENDFACTOR_DST_COLOR;
    529    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
    530       return PIPE_BLENDFACTOR_INV_DST_COLOR;
    531    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
    532       return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
    533    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
    534       return PIPE_BLENDFACTOR_CONST_COLOR;
    535    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
    536       return PIPE_BLENDFACTOR_INV_CONST_COLOR;
    537    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
    538       return PIPE_BLENDFACTOR_CONST_ALPHA;
    539    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
    540       return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
    541    default:
    542       assert(0);
    543       return PIPE_BLENDFACTOR_ONE;
    544    }
    545 }
    546 
    547 static unsigned
    548 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
    549 {
    550    switch (equation) {
    551    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
    552       return PIPE_BLEND_SUBTRACT;
    553    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
    554       return PIPE_BLEND_REVERSE_SUBTRACT;
    555    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
    556       return PIPE_BLEND_ADD;
    557    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
    558       return PIPE_BLEND_MIN;
    559    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
    560       return PIPE_BLEND_MAX;
    561    default:
    562       assert(0);
    563       return PIPE_BLEND_ADD;
    564    }
    565 }
    566 
    567 static void *
    568 BlenderToPipe(struct pipe_context *context,
    569               VdpOutputSurfaceRenderBlendState const *blend_state)
    570 {
    571    struct pipe_blend_state blend;
    572 
    573    memset(&blend, 0, sizeof blend);
    574    blend.independent_blend_enable = 0;
    575 
    576    if (blend_state) {
    577       blend.rt[0].blend_enable = 1;
    578       blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
    579       blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
    580       blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
    581       blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
    582       blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
    583       blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
    584    } else {
    585       blend.rt[0].blend_enable = 0;
    586    }
    587 
    588    blend.logicop_enable = 0;
    589    blend.logicop_func = PIPE_LOGICOP_CLEAR;
    590    blend.rt[0].colormask = PIPE_MASK_RGBA;
    591    blend.dither = 0;
    592 
    593    return context->create_blend_state(context, &blend);
    594 }
    595 
    596 static struct vertex4f *
    597 ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
    598 {
    599    unsigned i;
    600    struct vertex4f *dst = result;
    601 
    602    if (!colors)
    603       return NULL;
    604 
    605    for (i = 0; i < 4; ++i) {
    606       dst->x = colors->red;
    607       dst->y = colors->green;
    608       dst->z = colors->blue;
    609       dst->w = colors->alpha;
    610 
    611       ++dst;
    612       if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
    613          ++colors;
    614    }
    615    return result;
    616 }
    617 
    618 /**
    619  * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
    620  * another VdpOutputSurface; Output Surface object VdpOutputSurface.
    621  */
    622 VdpStatus
    623 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
    624                                       VdpRect const *destination_rect,
    625                                       VdpOutputSurface source_surface,
    626                                       VdpRect const *source_rect,
    627                                       VdpColor const *colors,
    628                                       VdpOutputSurfaceRenderBlendState const *blend_state,
    629                                       uint32_t flags)
    630 {
    631    vlVdpOutputSurface *dst_vlsurface;
    632    vlVdpOutputSurface *src_vlsurface;
    633 
    634    struct pipe_context *context;
    635    struct vl_compositor *compositor;
    636    struct vl_compositor_state *cstate;
    637 
    638    struct u_rect src_rect, dst_rect;
    639 
    640    struct vertex4f vlcolors[4];
    641    void *blend;
    642 
    643    dst_vlsurface = vlGetDataHTAB(destination_surface);
    644    if (!dst_vlsurface)
    645       return VDP_STATUS_INVALID_HANDLE;
    646 
    647    src_vlsurface = vlGetDataHTAB(source_surface);
    648    if (!src_vlsurface)
    649       return VDP_STATUS_INVALID_HANDLE;
    650 
    651    if (dst_vlsurface->device != src_vlsurface->device)
    652       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
    653 
    654    pipe_mutex_lock(dst_vlsurface->device->mutex);
    655    vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
    656 
    657    context = dst_vlsurface->device->context;
    658    compositor = &dst_vlsurface->device->compositor;
    659    cstate = &dst_vlsurface->cstate;
    660 
    661    blend = BlenderToPipe(context, blend_state);
    662 
    663    vl_compositor_clear_layers(cstate);
    664    vl_compositor_set_layer_blend(cstate, 0, blend, false);
    665    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
    666                                 RectToPipe(source_rect, &src_rect), NULL,
    667                                 ColorsToPipe(colors, flags, vlcolors));
    668    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
    669    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
    670 
    671    context->delete_blend_state(context, blend);
    672    pipe_mutex_unlock(dst_vlsurface->device->mutex);
    673 
    674    return VDP_STATUS_OK;
    675 }
    676 
    677 /**
    678  * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
    679  * a VdpOutputSurface; Output Surface object VdpOutputSurface.
    680  */
    681 VdpStatus
    682 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
    683                                       VdpRect const *destination_rect,
    684                                       VdpBitmapSurface source_surface,
    685                                       VdpRect const *source_rect,
    686                                       VdpColor const *colors,
    687                                       VdpOutputSurfaceRenderBlendState const *blend_state,
    688                                       uint32_t flags)
    689 {
    690    vlVdpOutputSurface *dst_vlsurface;
    691    vlVdpBitmapSurface *src_vlsurface;
    692 
    693    struct pipe_context *context;
    694    struct vl_compositor *compositor;
    695    struct vl_compositor_state *cstate;
    696 
    697    struct u_rect src_rect, dst_rect;
    698 
    699    struct vertex4f vlcolors[4];
    700    void *blend;
    701 
    702    dst_vlsurface = vlGetDataHTAB(destination_surface);
    703    if (!dst_vlsurface)
    704       return VDP_STATUS_INVALID_HANDLE;
    705 
    706    src_vlsurface = vlGetDataHTAB(source_surface);
    707    if (!src_vlsurface)
    708       return VDP_STATUS_INVALID_HANDLE;
    709 
    710    if (dst_vlsurface->device != src_vlsurface->device)
    711       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
    712 
    713    context = dst_vlsurface->device->context;
    714    compositor = &dst_vlsurface->device->compositor;
    715    cstate = &dst_vlsurface->cstate;
    716 
    717    pipe_mutex_lock(dst_vlsurface->device->mutex);
    718    vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
    719 
    720    blend = BlenderToPipe(context, blend_state);
    721 
    722    vl_compositor_clear_layers(cstate);
    723    vl_compositor_set_layer_blend(cstate, 0, blend, false);
    724    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
    725                                 RectToPipe(source_rect, &src_rect), NULL,
    726                                 ColorsToPipe(colors, flags, vlcolors));
    727    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
    728    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
    729 
    730    context->delete_blend_state(context, blend);
    731    pipe_mutex_unlock(dst_vlsurface->device->mutex);
    732 
    733    return VDP_STATUS_OK;
    734 }
    735