Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2010 Thomas Balling Sørensen.
  4.  * Copyright 2011 Christian König.
  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.       FREE(vlsurface);
  90.       return VDP_STATUS_ERROR;
  91.    }
  92.  
  93.    vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
  94.    vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
  95.    if (!vlsurface->sampler_view) {
  96.       pipe_resource_reference(&res, NULL);
  97.       pipe_mutex_unlock(dev->mutex);
  98.       FREE(dev);
  99.       return VDP_STATUS_ERROR;
  100.    }
  101.  
  102.    memset(&surf_templ, 0, sizeof(surf_templ));
  103.    surf_templ.format = res->format;
  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.    map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer);
  211.    if (!map) {
  212.       pipe_mutex_unlock(vlsurface->device->mutex);
  213.       return VDP_STATUS_RESOURCES;
  214.    }
  215.  
  216.    util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
  217.                   box.width, box.height, map, transfer->stride, 0, 0);
  218.  
  219.    pipe_transfer_unmap(pipe, transfer);
  220.    pipe_mutex_unlock(vlsurface->device->mutex);
  221.  
  222.    return VDP_STATUS_OK;
  223. }
  224.  
  225. /**
  226.  * Copy image data from application memory in the surface's native format to
  227.  * a VdpOutputSurface.
  228.  */
  229. VdpStatus
  230. vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
  231.                                 void const *const *source_data,
  232.                                 uint32_t const *source_pitches,
  233.                                 VdpRect const *destination_rect)
  234. {
  235.    vlVdpOutputSurface *vlsurface;
  236.    struct pipe_box dst_box;
  237.    struct pipe_context *pipe;
  238.  
  239.    vlsurface = vlGetDataHTAB(surface);
  240.    if (!vlsurface)
  241.       return VDP_STATUS_INVALID_HANDLE;
  242.  
  243.    pipe = vlsurface->device->context;
  244.    if (!pipe)
  245.       return VDP_STATUS_INVALID_HANDLE;
  246.  
  247.    pipe_mutex_lock(vlsurface->device->mutex);
  248.    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
  249.  
  250.    dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
  251.    pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
  252.                                PIPE_TRANSFER_WRITE, &dst_box, *source_data,
  253.                                *source_pitches, 0);
  254.    pipe_mutex_unlock(vlsurface->device->mutex);
  255.  
  256.    return VDP_STATUS_OK;
  257. }
  258.  
  259. /**
  260.  * Copy image data from application memory in a specific indexed format to
  261.  * a VdpOutputSurface.
  262.  */
  263. VdpStatus
  264. vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
  265.                                  VdpIndexedFormat source_indexed_format,
  266.                                  void const *const *source_data,
  267.                                  uint32_t const *source_pitch,
  268.                                  VdpRect const *destination_rect,
  269.                                  VdpColorTableFormat color_table_format,
  270.                                  void const *color_table)
  271. {
  272.    vlVdpOutputSurface *vlsurface;
  273.    struct pipe_context *context;
  274.    struct vl_compositor *compositor;
  275.    struct vl_compositor_state *cstate;
  276.  
  277.    enum pipe_format index_format;
  278.    enum pipe_format colortbl_format;
  279.  
  280.    struct pipe_resource *res, res_tmpl;
  281.    struct pipe_sampler_view sv_tmpl;
  282.    struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
  283.  
  284.    struct pipe_box box;
  285.    struct u_rect dst_rect;
  286.  
  287.    vlsurface = vlGetDataHTAB(surface);
  288.    if (!vlsurface)
  289.       return VDP_STATUS_INVALID_HANDLE;
  290.  
  291.    context = vlsurface->device->context;
  292.    compositor = &vlsurface->device->compositor;
  293.    cstate = &vlsurface->cstate;
  294.  
  295.    index_format = FormatIndexedToPipe(source_indexed_format);
  296.    if (index_format == PIPE_FORMAT_NONE)
  297.        return VDP_STATUS_INVALID_INDEXED_FORMAT;
  298.  
  299.    if (!source_data || !source_pitch)
  300.        return VDP_STATUS_INVALID_POINTER;
  301.  
  302.    colortbl_format = FormatColorTableToPipe(color_table_format);
  303.    if (colortbl_format == PIPE_FORMAT_NONE)
  304.        return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
  305.  
  306.    if (!color_table)
  307.        return VDP_STATUS_INVALID_POINTER;
  308.  
  309.    memset(&res_tmpl, 0, sizeof(res_tmpl));
  310.    res_tmpl.target = PIPE_TEXTURE_2D;
  311.    res_tmpl.format = index_format;
  312.  
  313.    if (destination_rect) {
  314.       res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
  315.       res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
  316.    } else {
  317.       res_tmpl.width0 = vlsurface->surface->texture->width0;
  318.       res_tmpl.height0 = vlsurface->surface->texture->height0;
  319.    }
  320.    res_tmpl.depth0 = 1;
  321.    res_tmpl.array_size = 1;
  322.    res_tmpl.usage = PIPE_USAGE_STAGING;
  323.    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
  324.  
  325.    pipe_mutex_lock(vlsurface->device->mutex);
  326.    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
  327.  
  328.    res = context->screen->resource_create(context->screen, &res_tmpl);
  329.    if (!res)
  330.       goto error_resource;
  331.  
  332.    box.x = box.y = box.z = 0;
  333.    box.width = res->width0;
  334.    box.height = res->height0;
  335.    box.depth = res->depth0;
  336.  
  337.    context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
  338.                                   source_data[0], source_pitch[0],
  339.                                   source_pitch[0] * res->height0);
  340.  
  341.    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
  342.    u_sampler_view_default_template(&sv_tmpl, res, res->format);
  343.  
  344.    sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
  345.    pipe_resource_reference(&res, NULL);
  346.  
  347.    if (!sv_idx)
  348.       goto error_resource;
  349.  
  350.    memset(&res_tmpl, 0, sizeof(res_tmpl));
  351.    res_tmpl.target = PIPE_TEXTURE_1D;
  352.    res_tmpl.format = colortbl_format;
  353.    res_tmpl.width0 = 1 << util_format_get_component_bits(
  354.       index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
  355.    res_tmpl.height0 = 1;
  356.    res_tmpl.depth0 = 1;
  357.    res_tmpl.array_size = 1;
  358.    res_tmpl.usage = PIPE_USAGE_STAGING;
  359.    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
  360.  
  361.    res = context->screen->resource_create(context->screen, &res_tmpl);
  362.    if (!res)
  363.       goto error_resource;
  364.  
  365.    box.x = box.y = box.z = 0;
  366.    box.width = res->width0;
  367.    box.height = res->height0;
  368.    box.depth = res->depth0;
  369.  
  370.    context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
  371.                                   util_format_get_stride(colortbl_format, res->width0), 0);
  372.  
  373.    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
  374.    u_sampler_view_default_template(&sv_tmpl, res, res->format);
  375.  
  376.    sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
  377.    pipe_resource_reference(&res, NULL);
  378.  
  379.    if (!sv_tbl)
  380.       goto error_resource;
  381.  
  382.    vl_compositor_clear_layers(cstate);
  383.    vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
  384.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  385.    vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
  386.  
  387.    pipe_sampler_view_reference(&sv_idx, NULL);
  388.    pipe_sampler_view_reference(&sv_tbl, NULL);
  389.    pipe_mutex_unlock(vlsurface->device->mutex);
  390.  
  391.    return VDP_STATUS_OK;
  392.  
  393. error_resource:
  394.    pipe_sampler_view_reference(&sv_idx, NULL);
  395.    pipe_sampler_view_reference(&sv_tbl, NULL);
  396.    pipe_mutex_unlock(vlsurface->device->mutex);
  397.    return VDP_STATUS_RESOURCES;
  398. }
  399.  
  400. /**
  401.  * Copy image data from application memory in a specific YCbCr format to
  402.  * a VdpOutputSurface.
  403.  */
  404. VdpStatus
  405. vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
  406.                                VdpYCbCrFormat source_ycbcr_format,
  407.                                void const *const *source_data,
  408.                                uint32_t const *source_pitches,
  409.                                VdpRect const *destination_rect,
  410.                                VdpCSCMatrix const *csc_matrix)
  411. {
  412.    vlVdpOutputSurface *vlsurface;
  413.    struct vl_compositor *compositor;
  414.    struct vl_compositor_state *cstate;
  415.  
  416.    struct pipe_context *pipe;
  417.    enum pipe_format format;
  418.    struct pipe_video_buffer vtmpl, *vbuffer;
  419.    struct u_rect dst_rect;
  420.    struct pipe_sampler_view **sampler_views;
  421.  
  422.    unsigned i;
  423.  
  424.    vlsurface = vlGetDataHTAB(surface);
  425.    if (!vlsurface)
  426.       return VDP_STATUS_INVALID_HANDLE;
  427.  
  428.  
  429.    pipe = vlsurface->device->context;
  430.    compositor = &vlsurface->device->compositor;
  431.    cstate = &vlsurface->cstate;
  432.  
  433.    format = FormatYCBCRToPipe(source_ycbcr_format);
  434.    if (format == PIPE_FORMAT_NONE)
  435.        return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
  436.  
  437.    if (!source_data || !source_pitches)
  438.        return VDP_STATUS_INVALID_POINTER;
  439.  
  440.    pipe_mutex_lock(vlsurface->device->mutex);
  441.    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
  442.    memset(&vtmpl, 0, sizeof(vtmpl));
  443.    vtmpl.buffer_format = format;
  444.    vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
  445.  
  446.    if (destination_rect) {
  447.       vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
  448.       vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
  449.    } else {
  450.       vtmpl.width = vlsurface->surface->texture->width0;
  451.       vtmpl.height = vlsurface->surface->texture->height0;
  452.    }
  453.  
  454.    vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
  455.    if (!vbuffer) {
  456.       pipe_mutex_unlock(vlsurface->device->mutex);
  457.       return VDP_STATUS_RESOURCES;
  458.    }
  459.  
  460.    sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
  461.    if (!sampler_views) {
  462.       vbuffer->destroy(vbuffer);
  463.       pipe_mutex_unlock(vlsurface->device->mutex);
  464.       return VDP_STATUS_RESOURCES;
  465.    }
  466.  
  467.    for (i = 0; i < 3; ++i) {
  468.       struct pipe_sampler_view *sv = sampler_views[i];
  469.       if (!sv) continue;
  470.  
  471.       struct pipe_box dst_box = {
  472.          0, 0, 0,
  473.          sv->texture->width0, sv->texture->height0, 1
  474.       };
  475.  
  476.       pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
  477.                                   source_data[i], source_pitches[i], 0);
  478.    }
  479.  
  480.    if (!csc_matrix) {
  481.       vl_csc_matrix csc;
  482.       vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
  483.       vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
  484.    } else {
  485.       vl_compositor_set_csc_matrix(cstate, csc_matrix);
  486.    }
  487.  
  488.    vl_compositor_clear_layers(cstate);
  489.    vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
  490.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  491.    vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
  492.  
  493.    vbuffer->destroy(vbuffer);
  494.    pipe_mutex_unlock(vlsurface->device->mutex);
  495.  
  496.    return VDP_STATUS_OK;
  497. }
  498.  
  499. static unsigned
  500. BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
  501. {
  502.    switch (factor) {
  503.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
  504.       return PIPE_BLENDFACTOR_ZERO;
  505.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
  506.       return PIPE_BLENDFACTOR_ONE;
  507.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
  508.       return PIPE_BLENDFACTOR_SRC_COLOR;
  509.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
  510.       return PIPE_BLENDFACTOR_INV_SRC_COLOR;
  511.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
  512.       return PIPE_BLENDFACTOR_SRC_ALPHA;
  513.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
  514.       return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
  515.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
  516.       return PIPE_BLENDFACTOR_DST_ALPHA;
  517.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
  518.       return PIPE_BLENDFACTOR_INV_DST_ALPHA;
  519.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
  520.       return PIPE_BLENDFACTOR_DST_COLOR;
  521.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
  522.       return PIPE_BLENDFACTOR_INV_DST_COLOR;
  523.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
  524.       return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
  525.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
  526.       return PIPE_BLENDFACTOR_CONST_COLOR;
  527.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
  528.       return PIPE_BLENDFACTOR_INV_CONST_COLOR;
  529.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
  530.       return PIPE_BLENDFACTOR_CONST_ALPHA;
  531.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
  532.       return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
  533.    default:
  534.       assert(0);
  535.       return PIPE_BLENDFACTOR_ONE;
  536.    }
  537. }
  538.  
  539. static unsigned
  540. BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
  541. {
  542.    switch (equation) {
  543.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
  544.       return PIPE_BLEND_SUBTRACT;
  545.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
  546.       return PIPE_BLEND_REVERSE_SUBTRACT;
  547.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
  548.       return PIPE_BLEND_ADD;
  549.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
  550.       return PIPE_BLEND_MIN;
  551.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
  552.       return PIPE_BLEND_MAX;
  553.    default:
  554.       assert(0);
  555.       return PIPE_BLEND_ADD;
  556.    }
  557. }
  558.  
  559. static void *
  560. BlenderToPipe(struct pipe_context *context,
  561.               VdpOutputSurfaceRenderBlendState const *blend_state)
  562. {
  563.    struct pipe_blend_state blend;
  564.  
  565.    memset(&blend, 0, sizeof blend);
  566.    blend.independent_blend_enable = 0;
  567.  
  568.    if (blend_state) {
  569.       blend.rt[0].blend_enable = 1;
  570.       blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
  571.       blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
  572.       blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
  573.       blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
  574.       blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
  575.       blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
  576.    } else {
  577.       blend.rt[0].blend_enable = 0;
  578.    }
  579.  
  580.    blend.logicop_enable = 0;
  581.    blend.logicop_func = PIPE_LOGICOP_CLEAR;
  582.    blend.rt[0].colormask = PIPE_MASK_RGBA;
  583.    blend.dither = 0;
  584.  
  585.    return context->create_blend_state(context, &blend);
  586. }
  587.  
  588. static struct vertex4f *
  589. ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
  590. {
  591.    unsigned i;
  592.    struct vertex4f *dst = result;
  593.  
  594.    if (!colors)
  595.       return NULL;
  596.  
  597.    for (i = 0; i < 4; ++i) {
  598.       dst->x = colors->red;
  599.       dst->y = colors->green;
  600.       dst->z = colors->blue;
  601.       dst->w = colors->alpha;
  602.  
  603.       ++dst;
  604.       if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
  605.          ++colors;
  606.    }
  607.    return result;
  608. }
  609.  
  610. /**
  611.  * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
  612.  * another VdpOutputSurface; Output Surface object VdpOutputSurface.
  613.  */
  614. VdpStatus
  615. vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
  616.                                       VdpRect const *destination_rect,
  617.                                       VdpOutputSurface source_surface,
  618.                                       VdpRect const *source_rect,
  619.                                       VdpColor const *colors,
  620.                                       VdpOutputSurfaceRenderBlendState const *blend_state,
  621.                                       uint32_t flags)
  622. {
  623.    vlVdpOutputSurface *dst_vlsurface;
  624.    vlVdpOutputSurface *src_vlsurface;
  625.  
  626.    struct pipe_context *context;
  627.    struct vl_compositor *compositor;
  628.    struct vl_compositor_state *cstate;
  629.  
  630.    struct u_rect src_rect, dst_rect;
  631.  
  632.    struct vertex4f vlcolors[4];
  633.    void *blend;
  634.  
  635.    dst_vlsurface = vlGetDataHTAB(destination_surface);
  636.    if (!dst_vlsurface)
  637.       return VDP_STATUS_INVALID_HANDLE;
  638.  
  639.    src_vlsurface = vlGetDataHTAB(source_surface);
  640.    if (!src_vlsurface)
  641.       return VDP_STATUS_INVALID_HANDLE;
  642.  
  643.    if (dst_vlsurface->device != src_vlsurface->device)
  644.       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
  645.  
  646.    pipe_mutex_lock(dst_vlsurface->device->mutex);
  647.    vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
  648.  
  649.    context = dst_vlsurface->device->context;
  650.    compositor = &dst_vlsurface->device->compositor;
  651.    cstate = &dst_vlsurface->cstate;
  652.  
  653.    blend = BlenderToPipe(context, blend_state);
  654.  
  655.    vl_compositor_clear_layers(cstate);
  656.    vl_compositor_set_layer_blend(cstate, 0, blend, false);
  657.    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
  658.                                 RectToPipe(source_rect, &src_rect), NULL,
  659.                                 ColorsToPipe(colors, flags, vlcolors));
  660.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  661.    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
  662.  
  663.    context->delete_blend_state(context, blend);
  664.    pipe_mutex_unlock(dst_vlsurface->device->mutex);
  665.  
  666.    return VDP_STATUS_OK;
  667. }
  668.  
  669. /**
  670.  * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
  671.  * a VdpOutputSurface; Output Surface object VdpOutputSurface.
  672.  */
  673. VdpStatus
  674. vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
  675.                                       VdpRect const *destination_rect,
  676.                                       VdpBitmapSurface source_surface,
  677.                                       VdpRect const *source_rect,
  678.                                       VdpColor const *colors,
  679.                                       VdpOutputSurfaceRenderBlendState const *blend_state,
  680.                                       uint32_t flags)
  681. {
  682.    vlVdpOutputSurface *dst_vlsurface;
  683.    vlVdpBitmapSurface *src_vlsurface;
  684.  
  685.    struct pipe_context *context;
  686.    struct vl_compositor *compositor;
  687.    struct vl_compositor_state *cstate;
  688.  
  689.    struct u_rect src_rect, dst_rect;
  690.  
  691.    struct vertex4f vlcolors[4];
  692.    void *blend;
  693.  
  694.    dst_vlsurface = vlGetDataHTAB(destination_surface);
  695.    if (!dst_vlsurface)
  696.       return VDP_STATUS_INVALID_HANDLE;
  697.  
  698.    src_vlsurface = vlGetDataHTAB(source_surface);
  699.    if (!src_vlsurface)
  700.       return VDP_STATUS_INVALID_HANDLE;
  701.  
  702.    if (dst_vlsurface->device != src_vlsurface->device)
  703.       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
  704.  
  705.    context = dst_vlsurface->device->context;
  706.    compositor = &dst_vlsurface->device->compositor;
  707.    cstate = &dst_vlsurface->cstate;
  708.  
  709.    pipe_mutex_lock(dst_vlsurface->device->mutex);
  710.    vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
  711.  
  712.    blend = BlenderToPipe(context, blend_state);
  713.  
  714.    vl_compositor_clear_layers(cstate);
  715.    vl_compositor_set_layer_blend(cstate, 0, blend, false);
  716.    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
  717.                                 RectToPipe(source_rect, &src_rect), NULL,
  718.                                 ColorsToPipe(colors, flags, vlcolors));
  719.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  720.    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
  721.  
  722.    context->delete_blend_state(context, blend);
  723.    pipe_mutex_unlock(dst_vlsurface->device->mutex);
  724.  
  725.    return VDP_STATUS_OK;
  726. }
  727.