17ec681f3Smrg/************************************************************************** 27ec681f3Smrg * 37ec681f3Smrg * Copyright 2010 Thomas Balling Sørensen. 47ec681f3Smrg * Copyright 2011 Christian König. 57ec681f3Smrg * All Rights Reserved. 67ec681f3Smrg * 77ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87ec681f3Smrg * copy of this software and associated documentation files (the 97ec681f3Smrg * "Software"), to deal in the Software without restriction, including 107ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish, 117ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to 127ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to 137ec681f3Smrg * the following conditions: 147ec681f3Smrg * 157ec681f3Smrg * The above copyright notice and this permission notice (including the 167ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions 177ec681f3Smrg * of the Software. 187ec681f3Smrg * 197ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 207ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 217ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 227ec681f3Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 237ec681f3Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 247ec681f3Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 257ec681f3Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 267ec681f3Smrg * 277ec681f3Smrg **************************************************************************/ 287ec681f3Smrg 297ec681f3Smrg#include <assert.h> 307ec681f3Smrg 317ec681f3Smrg#include "pipe/p_state.h" 327ec681f3Smrg 337ec681f3Smrg#include "util/u_memory.h" 347ec681f3Smrg#include "util/u_debug.h" 357ec681f3Smrg#include "util/u_rect.h" 367ec681f3Smrg#include "util/u_surface.h" 377ec681f3Smrg#include "util/u_video.h" 387ec681f3Smrg#include "vl/vl_defines.h" 397ec681f3Smrg 407ec681f3Smrg#include "frontend/drm_driver.h" 417ec681f3Smrg 427ec681f3Smrg#include "vdpau_private.h" 437ec681f3Smrg 447ec681f3Smrgenum getbits_conversion { 457ec681f3Smrg CONVERSION_NONE, 467ec681f3Smrg CONVERSION_NV12_TO_YV12, 477ec681f3Smrg CONVERSION_YV12_TO_NV12, 487ec681f3Smrg CONVERSION_SWAP_YUYV_UYVY, 497ec681f3Smrg}; 507ec681f3Smrg 517ec681f3Smrg/** 527ec681f3Smrg * Create a VdpVideoSurface. 537ec681f3Smrg */ 547ec681f3SmrgVdpStatus 557ec681f3SmrgvlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type, 567ec681f3Smrg uint32_t width, uint32_t height, 577ec681f3Smrg VdpVideoSurface *surface) 587ec681f3Smrg{ 597ec681f3Smrg struct pipe_context *pipe; 607ec681f3Smrg vlVdpSurface *p_surf; 617ec681f3Smrg VdpStatus ret; 627ec681f3Smrg 637ec681f3Smrg if (!(width && height)) { 647ec681f3Smrg ret = VDP_STATUS_INVALID_SIZE; 657ec681f3Smrg goto inv_size; 667ec681f3Smrg } 677ec681f3Smrg 687ec681f3Smrg p_surf = CALLOC(1, sizeof(vlVdpSurface)); 697ec681f3Smrg if (!p_surf) { 707ec681f3Smrg ret = VDP_STATUS_RESOURCES; 717ec681f3Smrg goto no_res; 727ec681f3Smrg } 737ec681f3Smrg 747ec681f3Smrg vlVdpDevice *dev = vlGetDataHTAB(device); 757ec681f3Smrg if (!dev) { 767ec681f3Smrg ret = VDP_STATUS_INVALID_HANDLE; 777ec681f3Smrg goto inv_device; 787ec681f3Smrg } 797ec681f3Smrg 807ec681f3Smrg DeviceReference(&p_surf->device, dev); 817ec681f3Smrg pipe = dev->context; 827ec681f3Smrg 837ec681f3Smrg mtx_lock(&dev->mutex); 847ec681f3Smrg memset(&p_surf->templat, 0, sizeof(p_surf->templat)); 857ec681f3Smrg /* TODO: buffer_format should be selected to match chroma_type */ 867ec681f3Smrg p_surf->templat.buffer_format = pipe->screen->get_video_param 877ec681f3Smrg ( 887ec681f3Smrg pipe->screen, 897ec681f3Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 907ec681f3Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 917ec681f3Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT 927ec681f3Smrg ); 937ec681f3Smrg p_surf->templat.width = width; 947ec681f3Smrg p_surf->templat.height = height; 957ec681f3Smrg p_surf->templat.interlaced = pipe->screen->get_video_param 967ec681f3Smrg ( 977ec681f3Smrg pipe->screen, 987ec681f3Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 997ec681f3Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 1007ec681f3Smrg PIPE_VIDEO_CAP_PREFERS_INTERLACED 1017ec681f3Smrg ); 1027ec681f3Smrg if (p_surf->templat.buffer_format != PIPE_FORMAT_NONE) 1037ec681f3Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 1047ec681f3Smrg 1057ec681f3Smrg /* do not mandate early allocation of a video buffer */ 1067ec681f3Smrg vlVdpVideoSurfaceClear(p_surf); 1077ec681f3Smrg mtx_unlock(&dev->mutex); 1087ec681f3Smrg 1097ec681f3Smrg *surface = vlAddDataHTAB(p_surf); 1107ec681f3Smrg if (*surface == 0) { 1117ec681f3Smrg ret = VDP_STATUS_ERROR; 1127ec681f3Smrg goto no_handle; 1137ec681f3Smrg } 1147ec681f3Smrg 1157ec681f3Smrg return VDP_STATUS_OK; 1167ec681f3Smrg 1177ec681f3Smrgno_handle: 1187ec681f3Smrg p_surf->video_buffer->destroy(p_surf->video_buffer); 1197ec681f3Smrg 1207ec681f3Smrginv_device: 1217ec681f3Smrg DeviceReference(&p_surf->device, NULL); 1227ec681f3Smrg FREE(p_surf); 1237ec681f3Smrg 1247ec681f3Smrgno_res: 1257ec681f3Smrginv_size: 1267ec681f3Smrg return ret; 1277ec681f3Smrg} 1287ec681f3Smrg 1297ec681f3Smrg/** 1307ec681f3Smrg * Destroy a VdpVideoSurface. 1317ec681f3Smrg */ 1327ec681f3SmrgVdpStatus 1337ec681f3SmrgvlVdpVideoSurfaceDestroy(VdpVideoSurface surface) 1347ec681f3Smrg{ 1357ec681f3Smrg vlVdpSurface *p_surf; 1367ec681f3Smrg 1377ec681f3Smrg p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface); 1387ec681f3Smrg if (!p_surf) 1397ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 1407ec681f3Smrg 1417ec681f3Smrg mtx_lock(&p_surf->device->mutex); 1427ec681f3Smrg if (p_surf->video_buffer) 1437ec681f3Smrg p_surf->video_buffer->destroy(p_surf->video_buffer); 1447ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 1457ec681f3Smrg 1467ec681f3Smrg vlRemoveDataHTAB(surface); 1477ec681f3Smrg DeviceReference(&p_surf->device, NULL); 1487ec681f3Smrg FREE(p_surf); 1497ec681f3Smrg 1507ec681f3Smrg return VDP_STATUS_OK; 1517ec681f3Smrg} 1527ec681f3Smrg 1537ec681f3Smrg/** 1547ec681f3Smrg * Retrieve the parameters used to create a VdpVideoSurface. 1557ec681f3Smrg */ 1567ec681f3SmrgVdpStatus 1577ec681f3SmrgvlVdpVideoSurfaceGetParameters(VdpVideoSurface surface, 1587ec681f3Smrg VdpChromaType *chroma_type, 1597ec681f3Smrg uint32_t *width, uint32_t *height) 1607ec681f3Smrg{ 1617ec681f3Smrg if (!(width && height && chroma_type)) 1627ec681f3Smrg return VDP_STATUS_INVALID_POINTER; 1637ec681f3Smrg 1647ec681f3Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 1657ec681f3Smrg if (!p_surf) 1667ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 1677ec681f3Smrg 1687ec681f3Smrg if (p_surf->video_buffer) { 1697ec681f3Smrg *width = p_surf->video_buffer->width; 1707ec681f3Smrg *height = p_surf->video_buffer->height; 1717ec681f3Smrg *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->video_buffer->buffer_format)); 1727ec681f3Smrg } else { 1737ec681f3Smrg *width = p_surf->templat.width; 1747ec681f3Smrg *height = p_surf->templat.height; 1757ec681f3Smrg *chroma_type = PipeToChroma(pipe_format_to_chroma_format(p_surf->templat.buffer_format)); 1767ec681f3Smrg } 1777ec681f3Smrg 1787ec681f3Smrg return VDP_STATUS_OK; 1797ec681f3Smrg} 1807ec681f3Smrg 1817ec681f3Smrgstatic void 1827ec681f3SmrgvlVdpVideoSurfaceSize(vlVdpSurface *p_surf, int component, 1837ec681f3Smrg unsigned *width, unsigned *height) 1847ec681f3Smrg{ 1857ec681f3Smrg *width = p_surf->templat.width; 1867ec681f3Smrg *height = p_surf->templat.height; 1877ec681f3Smrg 1887ec681f3Smrg vl_video_buffer_adjust_size(width, height, component, 1897ec681f3Smrg pipe_format_to_chroma_format(p_surf->templat.buffer_format), 1907ec681f3Smrg p_surf->templat.interlaced); 1917ec681f3Smrg} 1927ec681f3Smrg 1937ec681f3Smrg/** 1947ec681f3Smrg * Copy image data from a VdpVideoSurface to application memory in a specified 1957ec681f3Smrg * YCbCr format. 1967ec681f3Smrg */ 1977ec681f3SmrgVdpStatus 1987ec681f3SmrgvlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, 1997ec681f3Smrg VdpYCbCrFormat destination_ycbcr_format, 2007ec681f3Smrg void *const *destination_data, 2017ec681f3Smrg uint32_t const *destination_pitches) 2027ec681f3Smrg{ 2037ec681f3Smrg vlVdpSurface *vlsurface; 2047ec681f3Smrg struct pipe_context *pipe; 2057ec681f3Smrg enum pipe_format format, buffer_format; 2067ec681f3Smrg struct pipe_sampler_view **sampler_views; 2077ec681f3Smrg enum getbits_conversion conversion = CONVERSION_NONE; 2087ec681f3Smrg unsigned i, j; 2097ec681f3Smrg 2107ec681f3Smrg vlsurface = vlGetDataHTAB(surface); 2117ec681f3Smrg if (!vlsurface) 2127ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 2137ec681f3Smrg 2147ec681f3Smrg pipe = vlsurface->device->context; 2157ec681f3Smrg if (!pipe) 2167ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 2177ec681f3Smrg 2187ec681f3Smrg if (!destination_data || !destination_pitches) 2197ec681f3Smrg return VDP_STATUS_INVALID_POINTER; 2207ec681f3Smrg 2217ec681f3Smrg format = FormatYCBCRToPipe(destination_ycbcr_format); 2227ec681f3Smrg if (format == PIPE_FORMAT_NONE) 2237ec681f3Smrg return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; 2247ec681f3Smrg 2257ec681f3Smrg if (vlsurface->video_buffer == NULL) 2267ec681f3Smrg return VDP_STATUS_INVALID_VALUE; 2277ec681f3Smrg 2287ec681f3Smrg buffer_format = vlsurface->video_buffer->buffer_format; 2297ec681f3Smrg if (format != buffer_format) { 2307ec681f3Smrg if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12) 2317ec681f3Smrg conversion = CONVERSION_NV12_TO_YV12; 2327ec681f3Smrg else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12) 2337ec681f3Smrg conversion = CONVERSION_YV12_TO_NV12; 2347ec681f3Smrg else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) || 2357ec681f3Smrg (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV)) 2367ec681f3Smrg conversion = CONVERSION_SWAP_YUYV_UYVY; 2377ec681f3Smrg else 2387ec681f3Smrg return VDP_STATUS_NO_IMPLEMENTATION; 2397ec681f3Smrg } 2407ec681f3Smrg 2417ec681f3Smrg mtx_lock(&vlsurface->device->mutex); 2427ec681f3Smrg sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer); 2437ec681f3Smrg if (!sampler_views) { 2447ec681f3Smrg mtx_unlock(&vlsurface->device->mutex); 2457ec681f3Smrg return VDP_STATUS_RESOURCES; 2467ec681f3Smrg } 2477ec681f3Smrg 2487ec681f3Smrg for (i = 0; i < 3; ++i) { 2497ec681f3Smrg unsigned width, height; 2507ec681f3Smrg struct pipe_sampler_view *sv = sampler_views[i]; 2517ec681f3Smrg if (!sv) continue; 2527ec681f3Smrg 2537ec681f3Smrg vlVdpVideoSurfaceSize(vlsurface, i, &width, &height); 2547ec681f3Smrg 2557ec681f3Smrg for (j = 0; j < sv->texture->array_size; ++j) { 2567ec681f3Smrg struct pipe_box box = { 2577ec681f3Smrg 0, 0, j, 2587ec681f3Smrg width, height, 1 2597ec681f3Smrg }; 2607ec681f3Smrg struct pipe_transfer *transfer; 2617ec681f3Smrg uint8_t *map; 2627ec681f3Smrg 2637ec681f3Smrg map = pipe->texture_map(pipe, sv->texture, 0, 2647ec681f3Smrg PIPE_MAP_READ, &box, &transfer); 2657ec681f3Smrg if (!map) { 2667ec681f3Smrg mtx_unlock(&vlsurface->device->mutex); 2677ec681f3Smrg return VDP_STATUS_RESOURCES; 2687ec681f3Smrg } 2697ec681f3Smrg 2707ec681f3Smrg if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) { 2717ec681f3Smrg u_copy_nv12_to_yv12(destination_data, destination_pitches, 2727ec681f3Smrg i, j, transfer->stride, sv->texture->array_size, 2737ec681f3Smrg map, box.width, box.height); 2747ec681f3Smrg } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) { 2757ec681f3Smrg u_copy_yv12_to_nv12(destination_data, destination_pitches, 2767ec681f3Smrg i, j, transfer->stride, sv->texture->array_size, 2777ec681f3Smrg map, box.width, box.height); 2787ec681f3Smrg } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) { 2797ec681f3Smrg u_copy_swap422_packed(destination_data, destination_pitches, 2807ec681f3Smrg i, j, transfer->stride, sv->texture->array_size, 2817ec681f3Smrg map, box.width, box.height); 2827ec681f3Smrg } else { 2837ec681f3Smrg util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format, 2847ec681f3Smrg destination_pitches[i] * sv->texture->array_size, 0, 0, 2857ec681f3Smrg box.width, box.height, map, transfer->stride, 0, 0); 2867ec681f3Smrg } 2877ec681f3Smrg 2887ec681f3Smrg pipe_texture_unmap(pipe, transfer); 2897ec681f3Smrg } 2907ec681f3Smrg } 2917ec681f3Smrg mtx_unlock(&vlsurface->device->mutex); 2927ec681f3Smrg 2937ec681f3Smrg return VDP_STATUS_OK; 2947ec681f3Smrg} 2957ec681f3Smrg 2967ec681f3Smrg/** 2977ec681f3Smrg * Copy image data from application memory in a specific YCbCr format to 2987ec681f3Smrg * a VdpVideoSurface. 2997ec681f3Smrg */ 3007ec681f3SmrgVdpStatus 3017ec681f3SmrgvlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface, 3027ec681f3Smrg VdpYCbCrFormat source_ycbcr_format, 3037ec681f3Smrg void const *const *source_data, 3047ec681f3Smrg uint32_t const *source_pitches) 3057ec681f3Smrg{ 3067ec681f3Smrg enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format); 3077ec681f3Smrg enum getbits_conversion conversion = CONVERSION_NONE; 3087ec681f3Smrg struct pipe_context *pipe; 3097ec681f3Smrg struct pipe_sampler_view **sampler_views; 3107ec681f3Smrg unsigned i, j; 3117ec681f3Smrg unsigned usage = PIPE_MAP_WRITE; 3127ec681f3Smrg 3137ec681f3Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 3147ec681f3Smrg if (!p_surf) 3157ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 3167ec681f3Smrg 3177ec681f3Smrg pipe = p_surf->device->context; 3187ec681f3Smrg if (!pipe) 3197ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 3207ec681f3Smrg 3217ec681f3Smrg if (!source_data || !source_pitches) 3227ec681f3Smrg return VDP_STATUS_INVALID_POINTER; 3237ec681f3Smrg 3247ec681f3Smrg mtx_lock(&p_surf->device->mutex); 3257ec681f3Smrg 3267ec681f3Smrg if (p_surf->video_buffer == NULL || 3277ec681f3Smrg ((pformat != p_surf->video_buffer->buffer_format))) { 3287ec681f3Smrg enum pipe_format nformat = pformat; 3297ec681f3Smrg struct pipe_screen *screen = pipe->screen; 3307ec681f3Smrg 3317ec681f3Smrg /* Determine the most suitable format for the new surface */ 3327ec681f3Smrg if (!screen->is_video_format_supported(screen, nformat, 3337ec681f3Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 3347ec681f3Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { 3357ec681f3Smrg nformat = screen->get_video_param(screen, 3367ec681f3Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 3377ec681f3Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 3387ec681f3Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT); 3397ec681f3Smrg if (nformat == PIPE_FORMAT_NONE) { 3407ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 3417ec681f3Smrg return VDP_STATUS_NO_IMPLEMENTATION; 3427ec681f3Smrg } 3437ec681f3Smrg } 3447ec681f3Smrg 3457ec681f3Smrg if (p_surf->video_buffer == NULL || 3467ec681f3Smrg nformat != p_surf->video_buffer->buffer_format) { 3477ec681f3Smrg /* destroy the old one */ 3487ec681f3Smrg if (p_surf->video_buffer) 3497ec681f3Smrg p_surf->video_buffer->destroy(p_surf->video_buffer); 3507ec681f3Smrg 3517ec681f3Smrg /* adjust the template parameters */ 3527ec681f3Smrg p_surf->templat.buffer_format = nformat; 3537ec681f3Smrg if (nformat == PIPE_FORMAT_YUYV || nformat == PIPE_FORMAT_UYVY) 3547ec681f3Smrg p_surf->templat.interlaced = false; 3557ec681f3Smrg 3567ec681f3Smrg /* and try to create the video buffer with the new format */ 3577ec681f3Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 3587ec681f3Smrg 3597ec681f3Smrg /* stil no luck? ok forget it we don't support it */ 3607ec681f3Smrg if (!p_surf->video_buffer) { 3617ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 3627ec681f3Smrg return VDP_STATUS_NO_IMPLEMENTATION; 3637ec681f3Smrg } 3647ec681f3Smrg vlVdpVideoSurfaceClear(p_surf); 3657ec681f3Smrg } 3667ec681f3Smrg } 3677ec681f3Smrg 3687ec681f3Smrg if (pformat != p_surf->video_buffer->buffer_format) { 3697ec681f3Smrg if (pformat == PIPE_FORMAT_YV12 && 3707ec681f3Smrg p_surf->video_buffer->buffer_format == PIPE_FORMAT_NV12) 3717ec681f3Smrg conversion = CONVERSION_YV12_TO_NV12; 3727ec681f3Smrg else { 3737ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 3747ec681f3Smrg return VDP_STATUS_NO_IMPLEMENTATION; 3757ec681f3Smrg } 3767ec681f3Smrg } 3777ec681f3Smrg 3787ec681f3Smrg sampler_views = p_surf->video_buffer->get_sampler_view_planes(p_surf->video_buffer); 3797ec681f3Smrg if (!sampler_views) { 3807ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 3817ec681f3Smrg return VDP_STATUS_RESOURCES; 3827ec681f3Smrg } 3837ec681f3Smrg 3847ec681f3Smrg for (i = 0; i < 3; ++i) { 3857ec681f3Smrg unsigned width, height; 3867ec681f3Smrg struct pipe_sampler_view *sv = sampler_views[i]; 3877ec681f3Smrg struct pipe_resource *tex; 3887ec681f3Smrg if (!sv || !source_pitches[i]) continue; 3897ec681f3Smrg 3907ec681f3Smrg tex = sv->texture; 3917ec681f3Smrg vlVdpVideoSurfaceSize(p_surf, i, &width, &height); 3927ec681f3Smrg 3937ec681f3Smrg for (j = 0; j < tex->array_size; ++j) { 3947ec681f3Smrg struct pipe_box dst_box = { 3957ec681f3Smrg 0, 0, j, 3967ec681f3Smrg width, height, 1 3977ec681f3Smrg }; 3987ec681f3Smrg 3997ec681f3Smrg if (conversion == CONVERSION_YV12_TO_NV12 && i == 1) { 4007ec681f3Smrg struct pipe_transfer *transfer; 4017ec681f3Smrg uint8_t *map; 4027ec681f3Smrg 4037ec681f3Smrg map = pipe->texture_map(pipe, tex, 0, usage, 4047ec681f3Smrg &dst_box, &transfer); 4057ec681f3Smrg if (!map) { 4067ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 4077ec681f3Smrg return VDP_STATUS_RESOURCES; 4087ec681f3Smrg } 4097ec681f3Smrg 4107ec681f3Smrg u_copy_nv12_from_yv12(source_data, source_pitches, 4117ec681f3Smrg i, j, transfer->stride, tex->array_size, 4127ec681f3Smrg map, dst_box.width, dst_box.height); 4137ec681f3Smrg 4147ec681f3Smrg pipe_texture_unmap(pipe, transfer); 4157ec681f3Smrg } else { 4167ec681f3Smrg pipe->texture_subdata(pipe, tex, 0, 4177ec681f3Smrg PIPE_MAP_WRITE, &dst_box, 4187ec681f3Smrg source_data[i] + source_pitches[i] * j, 4197ec681f3Smrg source_pitches[i] * tex->array_size, 4207ec681f3Smrg 0); 4217ec681f3Smrg } 4227ec681f3Smrg /* 4237ec681f3Smrg * This surface has already been synced 4247ec681f3Smrg * by the first map. 4257ec681f3Smrg */ 4267ec681f3Smrg usage |= PIPE_MAP_UNSYNCHRONIZED; 4277ec681f3Smrg } 4287ec681f3Smrg } 4297ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 4307ec681f3Smrg 4317ec681f3Smrg return VDP_STATUS_OK; 4327ec681f3Smrg} 4337ec681f3Smrg 4347ec681f3Smrg/** 4357ec681f3Smrg * Helper function to initially clear the VideoSurface after (re-)creation 4367ec681f3Smrg */ 4377ec681f3Smrgvoid 4387ec681f3SmrgvlVdpVideoSurfaceClear(vlVdpSurface *vlsurf) 4397ec681f3Smrg{ 4407ec681f3Smrg struct pipe_context *pipe = vlsurf->device->context; 4417ec681f3Smrg struct pipe_surface **surfaces; 4427ec681f3Smrg unsigned i; 4437ec681f3Smrg 4447ec681f3Smrg if (!vlsurf->video_buffer) 4457ec681f3Smrg return; 4467ec681f3Smrg 4477ec681f3Smrg surfaces = vlsurf->video_buffer->get_surfaces(vlsurf->video_buffer); 4487ec681f3Smrg for (i = 0; i < VL_MAX_SURFACES; ++i) { 4497ec681f3Smrg union pipe_color_union c = {}; 4507ec681f3Smrg 4517ec681f3Smrg if (!surfaces[i]) 4527ec681f3Smrg continue; 4537ec681f3Smrg 4547ec681f3Smrg if (i > !!vlsurf->templat.interlaced) 4557ec681f3Smrg c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; 4567ec681f3Smrg 4577ec681f3Smrg pipe->clear_render_target(pipe, surfaces[i], &c, 0, 0, 4587ec681f3Smrg surfaces[i]->width, surfaces[i]->height, false); 4597ec681f3Smrg } 4607ec681f3Smrg pipe->flush(pipe, NULL, 0); 4617ec681f3Smrg} 4627ec681f3Smrg 4637ec681f3Smrg/** 4647ec681f3Smrg * Interop for the GL gallium frontend 4657ec681f3Smrg */ 4667ec681f3Smrgstruct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface) 4677ec681f3Smrg{ 4687ec681f3Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 4697ec681f3Smrg if (!p_surf) 4707ec681f3Smrg return NULL; 4717ec681f3Smrg 4727ec681f3Smrg mtx_lock(&p_surf->device->mutex); 4737ec681f3Smrg if (p_surf->video_buffer == NULL) { 4747ec681f3Smrg struct pipe_context *pipe = p_surf->device->context; 4757ec681f3Smrg 4767ec681f3Smrg /* try to create a video buffer if we don't already have one */ 4777ec681f3Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 4787ec681f3Smrg } 4797ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 4807ec681f3Smrg 4817ec681f3Smrg return p_surf->video_buffer; 4827ec681f3Smrg} 4837ec681f3Smrg 4847ec681f3SmrgVdpStatus vlVdpVideoSurfaceDMABuf(VdpVideoSurface surface, 4857ec681f3Smrg VdpVideoSurfacePlane plane, 4867ec681f3Smrg struct VdpSurfaceDMABufDesc *result) 4877ec681f3Smrg{ 4887ec681f3Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 4897ec681f3Smrg 4907ec681f3Smrg struct pipe_screen *pscreen; 4917ec681f3Smrg struct winsys_handle whandle; 4927ec681f3Smrg 4937ec681f3Smrg struct pipe_surface *surf; 4947ec681f3Smrg 4957ec681f3Smrg if (!p_surf) 4967ec681f3Smrg return VDP_STATUS_INVALID_HANDLE; 4977ec681f3Smrg 4987ec681f3Smrg if (plane > 3) 4997ec681f3Smrg return VDP_STATUS_INVALID_VALUE; 5007ec681f3Smrg 5017ec681f3Smrg if (!result) 5027ec681f3Smrg return VDP_STATUS_INVALID_POINTER; 5037ec681f3Smrg 5047ec681f3Smrg memset(result, 0, sizeof(*result)); 5057ec681f3Smrg result->handle = -1; 5067ec681f3Smrg 5077ec681f3Smrg mtx_lock(&p_surf->device->mutex); 5087ec681f3Smrg if (p_surf->video_buffer == NULL) { 5097ec681f3Smrg struct pipe_context *pipe = p_surf->device->context; 5107ec681f3Smrg 5117ec681f3Smrg /* try to create a video buffer if we don't already have one */ 5127ec681f3Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 5137ec681f3Smrg } 5147ec681f3Smrg 5157ec681f3Smrg /* Check if surface match interop requirements */ 5167ec681f3Smrg if (p_surf->video_buffer == NULL || !p_surf->video_buffer->interlaced || 5177ec681f3Smrg p_surf->video_buffer->buffer_format != PIPE_FORMAT_NV12) { 5187ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 5197ec681f3Smrg return VDP_STATUS_NO_IMPLEMENTATION; 5207ec681f3Smrg } 5217ec681f3Smrg 5227ec681f3Smrg surf = p_surf->video_buffer->get_surfaces(p_surf->video_buffer)[plane]; 5237ec681f3Smrg if (!surf) { 5247ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 5257ec681f3Smrg return VDP_STATUS_RESOURCES; 5267ec681f3Smrg } 5277ec681f3Smrg 5287ec681f3Smrg memset(&whandle, 0, sizeof(struct winsys_handle)); 5297ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_FD; 5307ec681f3Smrg whandle.layer = surf->u.tex.first_layer; 5317ec681f3Smrg 5327ec681f3Smrg pscreen = surf->texture->screen; 5337ec681f3Smrg if (!pscreen->resource_get_handle(pscreen, p_surf->device->context, 5347ec681f3Smrg surf->texture, &whandle, 5357ec681f3Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { 5367ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 5377ec681f3Smrg return VDP_STATUS_NO_IMPLEMENTATION; 5387ec681f3Smrg } 5397ec681f3Smrg 5407ec681f3Smrg mtx_unlock(&p_surf->device->mutex); 5417ec681f3Smrg 5427ec681f3Smrg result->handle = whandle.handle; 5437ec681f3Smrg result->width = surf->width; 5447ec681f3Smrg result->height = surf->height; 5457ec681f3Smrg result->offset = whandle.offset; 5467ec681f3Smrg result->stride = whandle.stride; 5477ec681f3Smrg 5487ec681f3Smrg if (surf->format == PIPE_FORMAT_R8_UNORM) 5497ec681f3Smrg result->format = VDP_RGBA_FORMAT_R8; 5507ec681f3Smrg else 5517ec681f3Smrg result->format = VDP_RGBA_FORMAT_R8G8; 5527ec681f3Smrg 5537ec681f3Smrg return VDP_STATUS_OK; 5547ec681f3Smrg} 555