Subversion Repositories Kolibri OS

Rev

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 VMWARE 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. #include "util/u_surface.h"
  36.  
  37. #include "vl/vl_csc.h"
  38.  
  39. #include "vdpau_private.h"
  40.  
  41. /**
  42.  * Create a VdpOutputSurface.
  43.  */
  44. VdpStatus
  45. vlVdpOutputSurfaceCreate(VdpDevice device,
  46.                          VdpRGBAFormat rgba_format,
  47.                          uint32_t width, uint32_t height,
  48.                          VdpOutputSurface  *surface)
  49. {
  50.    struct pipe_context *pipe;
  51.    struct pipe_resource res_tmpl, *res;
  52.    struct pipe_sampler_view sv_templ;
  53.    struct pipe_surface surf_templ;
  54.  
  55.    vlVdpOutputSurface *vlsurface = NULL;
  56.  
  57.    if (!(width && height))
  58.       return VDP_STATUS_INVALID_SIZE;
  59.  
  60.    vlVdpDevice *dev = vlGetDataHTAB(device);
  61.    if (!dev)
  62.       return VDP_STATUS_INVALID_HANDLE;
  63.  
  64.    pipe = dev->context;
  65.    if (!pipe)
  66.       return VDP_STATUS_INVALID_HANDLE;
  67.  
  68.    vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface));
  69.    if (!vlsurface)
  70.       return VDP_STATUS_RESOURCES;
  71.  
  72.    DeviceReference(&vlsurface->device, dev);
  73.  
  74.    memset(&res_tmpl, 0, sizeof(res_tmpl));
  75.  
  76.    res_tmpl.target = PIPE_TEXTURE_2D;
  77.    res_tmpl.format = FormatRGBAToPipe(rgba_format);
  78.    res_tmpl.width0 = width;
  79.    res_tmpl.height0 = height;
  80.    res_tmpl.depth0 = 1;
  81.    res_tmpl.array_size = 1;
  82.    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
  83.    res_tmpl.usage = PIPE_USAGE_DEFAULT;
  84.  
  85.    pipe_mutex_lock(dev->mutex);
  86.  
  87.    if (!CheckSurfaceParams(pipe->screen, &res_tmpl))
  88.       goto err_unlock;
  89.  
  90.    res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
  91.    if (!res)
  92.       goto err_unlock;
  93.  
  94.    vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
  95.    vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
  96.    if (!vlsurface->sampler_view)
  97.       goto err_resource;
  98.  
  99.    memset(&surf_templ, 0, sizeof(surf_templ));
  100.    surf_templ.format = res->format;
  101.    vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
  102.    if (!vlsurface->surface)
  103.       goto err_resource;
  104.  
  105.    *surface = vlAddDataHTAB(vlsurface);
  106.    if (*surface == 0)
  107.       goto err_resource;
  108.  
  109.    pipe_resource_reference(&res, NULL);
  110.  
  111.    vl_compositor_init_state(&vlsurface->cstate, pipe);
  112.    vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
  113.    pipe_mutex_unlock(dev->mutex);
  114.  
  115.    return VDP_STATUS_OK;
  116.  
  117. err_resource:
  118.    pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
  119.    pipe_surface_reference(&vlsurface->surface, NULL);
  120.    pipe_resource_reference(&res, NULL);
  121. err_unlock:
  122.    pipe_mutex_unlock(dev->mutex);
  123.    DeviceReference(&vlsurface->device, NULL);
  124.    FREE(vlsurface);
  125.    return VDP_STATUS_ERROR;
  126. }
  127.  
  128. /**
  129.  * Destroy a VdpOutputSurface.
  130.  */
  131. VdpStatus
  132. vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
  133. {
  134.    vlVdpOutputSurface *vlsurface;
  135.    struct pipe_context *pipe;
  136.  
  137.    vlsurface = vlGetDataHTAB(surface);
  138.    if (!vlsurface)
  139.       return VDP_STATUS_INVALID_HANDLE;
  140.  
  141.    pipe = vlsurface->device->context;
  142.  
  143.    pipe_mutex_lock(vlsurface->device->mutex);
  144.    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
  145.  
  146.    pipe_surface_reference(&vlsurface->surface, NULL);
  147.    pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
  148.    pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL);
  149.    vl_compositor_cleanup_state(&vlsurface->cstate);
  150.    pipe_mutex_unlock(vlsurface->device->mutex);
  151.  
  152.    vlRemoveDataHTAB(surface);
  153.    DeviceReference(&vlsurface->device, NULL);
  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.    if (!CheckSurfaceParams(context->screen, &res_tmpl))
  329.       goto error_resource;
  330.  
  331.    res = context->screen->resource_create(context->screen, &res_tmpl);
  332.    if (!res)
  333.       goto error_resource;
  334.  
  335.    box.x = box.y = box.z = 0;
  336.    box.width = res->width0;
  337.    box.height = res->height0;
  338.    box.depth = res->depth0;
  339.  
  340.    context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
  341.                                   source_data[0], source_pitch[0],
  342.                                   source_pitch[0] * res->height0);
  343.  
  344.    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
  345.    u_sampler_view_default_template(&sv_tmpl, res, res->format);
  346.  
  347.    sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
  348.    pipe_resource_reference(&res, NULL);
  349.  
  350.    if (!sv_idx)
  351.       goto error_resource;
  352.  
  353.    memset(&res_tmpl, 0, sizeof(res_tmpl));
  354.    res_tmpl.target = PIPE_TEXTURE_1D;
  355.    res_tmpl.format = colortbl_format;
  356.    res_tmpl.width0 = 1 << util_format_get_component_bits(
  357.       index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
  358.    res_tmpl.height0 = 1;
  359.    res_tmpl.depth0 = 1;
  360.    res_tmpl.array_size = 1;
  361.    res_tmpl.usage = PIPE_USAGE_STAGING;
  362.    res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
  363.  
  364.    res = context->screen->resource_create(context->screen, &res_tmpl);
  365.    if (!res)
  366.       goto error_resource;
  367.  
  368.    box.x = box.y = box.z = 0;
  369.    box.width = res->width0;
  370.    box.height = res->height0;
  371.    box.depth = res->depth0;
  372.  
  373.    context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
  374.                                   util_format_get_stride(colortbl_format, res->width0), 0);
  375.  
  376.    memset(&sv_tmpl, 0, sizeof(sv_tmpl));
  377.    u_sampler_view_default_template(&sv_tmpl, res, res->format);
  378.  
  379.    sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
  380.    pipe_resource_reference(&res, NULL);
  381.  
  382.    if (!sv_tbl)
  383.       goto error_resource;
  384.  
  385.    vl_compositor_clear_layers(cstate);
  386.    vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
  387.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  388.    vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
  389.  
  390.    pipe_sampler_view_reference(&sv_idx, NULL);
  391.    pipe_sampler_view_reference(&sv_tbl, NULL);
  392.    pipe_mutex_unlock(vlsurface->device->mutex);
  393.  
  394.    return VDP_STATUS_OK;
  395.  
  396. error_resource:
  397.    pipe_sampler_view_reference(&sv_idx, NULL);
  398.    pipe_sampler_view_reference(&sv_tbl, NULL);
  399.    pipe_mutex_unlock(vlsurface->device->mutex);
  400.    return VDP_STATUS_RESOURCES;
  401. }
  402.  
  403. /**
  404.  * Copy image data from application memory in a specific YCbCr format to
  405.  * a VdpOutputSurface.
  406.  */
  407. VdpStatus
  408. vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
  409.                                VdpYCbCrFormat source_ycbcr_format,
  410.                                void const *const *source_data,
  411.                                uint32_t const *source_pitches,
  412.                                VdpRect const *destination_rect,
  413.                                VdpCSCMatrix const *csc_matrix)
  414. {
  415.    vlVdpOutputSurface *vlsurface;
  416.    struct vl_compositor *compositor;
  417.    struct vl_compositor_state *cstate;
  418.  
  419.    struct pipe_context *pipe;
  420.    enum pipe_format format;
  421.    struct pipe_video_buffer vtmpl, *vbuffer;
  422.    struct u_rect dst_rect;
  423.    struct pipe_sampler_view **sampler_views;
  424.  
  425.    unsigned i;
  426.  
  427.    vlsurface = vlGetDataHTAB(surface);
  428.    if (!vlsurface)
  429.       return VDP_STATUS_INVALID_HANDLE;
  430.  
  431.  
  432.    pipe = vlsurface->device->context;
  433.    compositor = &vlsurface->device->compositor;
  434.    cstate = &vlsurface->cstate;
  435.  
  436.    format = FormatYCBCRToPipe(source_ycbcr_format);
  437.    if (format == PIPE_FORMAT_NONE)
  438.        return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
  439.  
  440.    if (!source_data || !source_pitches)
  441.        return VDP_STATUS_INVALID_POINTER;
  442.  
  443.    pipe_mutex_lock(vlsurface->device->mutex);
  444.    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
  445.    memset(&vtmpl, 0, sizeof(vtmpl));
  446.    vtmpl.buffer_format = format;
  447.    vtmpl.chroma_format = FormatYCBCRToPipeChroma(source_ycbcr_format);
  448.  
  449.    if (destination_rect) {
  450.       vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
  451.       vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
  452.    } else {
  453.       vtmpl.width = vlsurface->surface->texture->width0;
  454.       vtmpl.height = vlsurface->surface->texture->height0;
  455.    }
  456.  
  457.    vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
  458.    if (!vbuffer) {
  459.       pipe_mutex_unlock(vlsurface->device->mutex);
  460.       return VDP_STATUS_RESOURCES;
  461.    }
  462.  
  463.    sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
  464.    if (!sampler_views) {
  465.       vbuffer->destroy(vbuffer);
  466.       pipe_mutex_unlock(vlsurface->device->mutex);
  467.       return VDP_STATUS_RESOURCES;
  468.    }
  469.  
  470.    for (i = 0; i < 3; ++i) {
  471.       struct pipe_sampler_view *sv = sampler_views[i];
  472.       if (!sv) continue;
  473.  
  474.       struct pipe_box dst_box = {
  475.          0, 0, 0,
  476.          sv->texture->width0, sv->texture->height0, 1
  477.       };
  478.  
  479.       pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
  480.                                   source_data[i], source_pitches[i], 0);
  481.    }
  482.  
  483.    if (!csc_matrix) {
  484.       vl_csc_matrix csc;
  485.       vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
  486.       vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
  487.    } else {
  488.       vl_compositor_set_csc_matrix(cstate, csc_matrix);
  489.    }
  490.  
  491.    vl_compositor_clear_layers(cstate);
  492.    vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
  493.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  494.    vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false);
  495.  
  496.    vbuffer->destroy(vbuffer);
  497.    pipe_mutex_unlock(vlsurface->device->mutex);
  498.  
  499.    return VDP_STATUS_OK;
  500. }
  501.  
  502. static unsigned
  503. BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
  504. {
  505.    switch (factor) {
  506.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
  507.       return PIPE_BLENDFACTOR_ZERO;
  508.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
  509.       return PIPE_BLENDFACTOR_ONE;
  510.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
  511.       return PIPE_BLENDFACTOR_SRC_COLOR;
  512.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
  513.       return PIPE_BLENDFACTOR_INV_SRC_COLOR;
  514.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
  515.       return PIPE_BLENDFACTOR_SRC_ALPHA;
  516.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
  517.       return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
  518.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
  519.       return PIPE_BLENDFACTOR_DST_ALPHA;
  520.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
  521.       return PIPE_BLENDFACTOR_INV_DST_ALPHA;
  522.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
  523.       return PIPE_BLENDFACTOR_DST_COLOR;
  524.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
  525.       return PIPE_BLENDFACTOR_INV_DST_COLOR;
  526.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
  527.       return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
  528.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
  529.       return PIPE_BLENDFACTOR_CONST_COLOR;
  530.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
  531.       return PIPE_BLENDFACTOR_INV_CONST_COLOR;
  532.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
  533.       return PIPE_BLENDFACTOR_CONST_ALPHA;
  534.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
  535.       return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
  536.    default:
  537.       assert(0);
  538.       return PIPE_BLENDFACTOR_ONE;
  539.    }
  540. }
  541.  
  542. static unsigned
  543. BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
  544. {
  545.    switch (equation) {
  546.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
  547.       return PIPE_BLEND_SUBTRACT;
  548.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
  549.       return PIPE_BLEND_REVERSE_SUBTRACT;
  550.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
  551.       return PIPE_BLEND_ADD;
  552.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
  553.       return PIPE_BLEND_MIN;
  554.    case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
  555.       return PIPE_BLEND_MAX;
  556.    default:
  557.       assert(0);
  558.       return PIPE_BLEND_ADD;
  559.    }
  560. }
  561.  
  562. static void *
  563. BlenderToPipe(struct pipe_context *context,
  564.               VdpOutputSurfaceRenderBlendState const *blend_state)
  565. {
  566.    struct pipe_blend_state blend;
  567.  
  568.    memset(&blend, 0, sizeof blend);
  569.    blend.independent_blend_enable = 0;
  570.  
  571.    if (blend_state) {
  572.       blend.rt[0].blend_enable = 1;
  573.       blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
  574.       blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
  575.       blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
  576.       blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
  577.       blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
  578.       blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
  579.    } else {
  580.       blend.rt[0].blend_enable = 0;
  581.    }
  582.  
  583.    blend.logicop_enable = 0;
  584.    blend.logicop_func = PIPE_LOGICOP_CLEAR;
  585.    blend.rt[0].colormask = PIPE_MASK_RGBA;
  586.    blend.dither = 0;
  587.  
  588.    return context->create_blend_state(context, &blend);
  589. }
  590.  
  591. static struct vertex4f *
  592. ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
  593. {
  594.    unsigned i;
  595.    struct vertex4f *dst = result;
  596.  
  597.    if (!colors)
  598.       return NULL;
  599.  
  600.    for (i = 0; i < 4; ++i) {
  601.       dst->x = colors->red;
  602.       dst->y = colors->green;
  603.       dst->z = colors->blue;
  604.       dst->w = colors->alpha;
  605.  
  606.       ++dst;
  607.       if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
  608.          ++colors;
  609.    }
  610.    return result;
  611. }
  612.  
  613. /**
  614.  * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
  615.  * another VdpOutputSurface; Output Surface object VdpOutputSurface.
  616.  */
  617. VdpStatus
  618. vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
  619.                                       VdpRect const *destination_rect,
  620.                                       VdpOutputSurface source_surface,
  621.                                       VdpRect const *source_rect,
  622.                                       VdpColor const *colors,
  623.                                       VdpOutputSurfaceRenderBlendState const *blend_state,
  624.                                       uint32_t flags)
  625. {
  626.    vlVdpOutputSurface *dst_vlsurface;
  627.  
  628.    struct pipe_context *context;
  629.    struct pipe_sampler_view *src_sv;
  630.    struct vl_compositor *compositor;
  631.    struct vl_compositor_state *cstate;
  632.  
  633.    struct u_rect src_rect, dst_rect;
  634.  
  635.    struct vertex4f vlcolors[4];
  636.    void *blend;
  637.  
  638.    dst_vlsurface = vlGetDataHTAB(destination_surface);
  639.    if (!dst_vlsurface)
  640.       return VDP_STATUS_INVALID_HANDLE;
  641.  
  642.    if (source_surface == VDP_INVALID_HANDLE) {
  643.       src_sv = dst_vlsurface->device->dummy_sv;
  644.  
  645.    } else {
  646.       vlVdpOutputSurface *src_vlsurface = vlGetDataHTAB(source_surface);
  647.       if (!src_vlsurface)
  648.          return VDP_STATUS_INVALID_HANDLE;
  649.  
  650.       if (dst_vlsurface->device != src_vlsurface->device)
  651.          return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
  652.  
  653.       src_sv = src_vlsurface->sampler_view;
  654.    }
  655.  
  656.    pipe_mutex_lock(dst_vlsurface->device->mutex);
  657.    vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
  658.  
  659.    context = dst_vlsurface->device->context;
  660.    compositor = &dst_vlsurface->device->compositor;
  661.    cstate = &dst_vlsurface->cstate;
  662.  
  663.    blend = BlenderToPipe(context, blend_state);
  664.  
  665.    vl_compositor_clear_layers(cstate);
  666.    vl_compositor_set_layer_blend(cstate, 0, blend, false);
  667.    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv,
  668.                                 RectToPipe(source_rect, &src_rect), NULL,
  669.                                 ColorsToPipe(colors, flags, vlcolors));
  670.    STATIC_ASSERT(VL_COMPOSITOR_ROTATE_0 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
  671.    STATIC_ASSERT(VL_COMPOSITOR_ROTATE_90 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_90);
  672.    STATIC_ASSERT(VL_COMPOSITOR_ROTATE_180 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_180);
  673.    STATIC_ASSERT(VL_COMPOSITOR_ROTATE_270 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_270);
  674.    vl_compositor_set_layer_rotation(cstate, 0, flags & 3);
  675.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  676.    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
  677.  
  678.    context->delete_blend_state(context, blend);
  679.    pipe_mutex_unlock(dst_vlsurface->device->mutex);
  680.  
  681.    return VDP_STATUS_OK;
  682. }
  683.  
  684. /**
  685.  * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
  686.  * a VdpOutputSurface; Output Surface object VdpOutputSurface.
  687.  */
  688. VdpStatus
  689. vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
  690.                                       VdpRect const *destination_rect,
  691.                                       VdpBitmapSurface source_surface,
  692.                                       VdpRect const *source_rect,
  693.                                       VdpColor const *colors,
  694.                                       VdpOutputSurfaceRenderBlendState const *blend_state,
  695.                                       uint32_t flags)
  696. {
  697.    vlVdpOutputSurface *dst_vlsurface;
  698.  
  699.    struct pipe_context *context;
  700.    struct pipe_sampler_view *src_sv;
  701.    struct vl_compositor *compositor;
  702.    struct vl_compositor_state *cstate;
  703.  
  704.    struct u_rect src_rect, dst_rect;
  705.  
  706.    struct vertex4f vlcolors[4];
  707.    void *blend;
  708.  
  709.    dst_vlsurface = vlGetDataHTAB(destination_surface);
  710.    if (!dst_vlsurface)
  711.       return VDP_STATUS_INVALID_HANDLE;
  712.  
  713.    if (source_surface == VDP_INVALID_HANDLE) {
  714.       src_sv = dst_vlsurface->device->dummy_sv;
  715.  
  716.    } else {
  717.       vlVdpBitmapSurface *src_vlsurface = vlGetDataHTAB(source_surface);
  718.       if (!src_vlsurface)
  719.          return VDP_STATUS_INVALID_HANDLE;
  720.  
  721.       if (dst_vlsurface->device != src_vlsurface->device)
  722.          return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
  723.  
  724.       src_sv = src_vlsurface->sampler_view;
  725.    }
  726.  
  727.    context = dst_vlsurface->device->context;
  728.    compositor = &dst_vlsurface->device->compositor;
  729.    cstate = &dst_vlsurface->cstate;
  730.  
  731.    pipe_mutex_lock(dst_vlsurface->device->mutex);
  732.    vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
  733.  
  734.    blend = BlenderToPipe(context, blend_state);
  735.  
  736.    vl_compositor_clear_layers(cstate);
  737.    vl_compositor_set_layer_blend(cstate, 0, blend, false);
  738.    vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv,
  739.                                 RectToPipe(source_rect, &src_rect), NULL,
  740.                                 ColorsToPipe(colors, flags, vlcolors));
  741.    vl_compositor_set_layer_rotation(cstate, 0, flags & 3);
  742.    vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
  743.    vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false);
  744.  
  745.    context->delete_blend_state(context, blend);
  746.    pipe_mutex_unlock(dst_vlsurface->device->mutex);
  747.  
  748.    return VDP_STATUS_OK;
  749. }
  750.  
  751. struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface)
  752. {
  753.    vlVdpOutputSurface *vlsurface;
  754.  
  755.    vlsurface = vlGetDataHTAB(surface);
  756.    if (!vlsurface || !vlsurface->surface)
  757.       return NULL;
  758.  
  759.    pipe_mutex_lock(vlsurface->device->mutex);
  760.    vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
  761.    vlsurface->device->context->flush(vlsurface->device->context, NULL, 0);
  762.    pipe_mutex_unlock(vlsurface->device->mutex);
  763.  
  764.    return vlsurface->surface->texture;
  765. }
  766.