1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2010 Thomas Balling Sørensen. 4848b8605Smrg * Copyright 2011 Christian König. 5848b8605Smrg * All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the 9848b8605Smrg * "Software"), to deal in the Software without restriction, including 10848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 11848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 12848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 13848b8605Smrg * the following conditions: 14848b8605Smrg * 15848b8605Smrg * The above copyright notice and this permission notice (including the 16848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 17848b8605Smrg * of the Software. 18848b8605Smrg * 19848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26848b8605Smrg * 27848b8605Smrg **************************************************************************/ 28848b8605Smrg 29848b8605Smrg#include <assert.h> 30848b8605Smrg 31848b8605Smrg#include "pipe/p_state.h" 32848b8605Smrg 33848b8605Smrg#include "util/u_memory.h" 34848b8605Smrg#include "util/u_debug.h" 35848b8605Smrg#include "util/u_rect.h" 36848b8605Smrg#include "util/u_surface.h" 37b8e80941Smrg#include "util/u_video.h" 38848b8605Smrg#include "vl/vl_defines.h" 39848b8605Smrg 40b8e80941Smrg#include "state_tracker/drm_driver.h" 41b8e80941Smrg 42848b8605Smrg#include "vdpau_private.h" 43848b8605Smrg 44848b8605Smrgenum getbits_conversion { 45848b8605Smrg CONVERSION_NONE, 46848b8605Smrg CONVERSION_NV12_TO_YV12, 47848b8605Smrg CONVERSION_YV12_TO_NV12, 48848b8605Smrg CONVERSION_SWAP_YUYV_UYVY, 49848b8605Smrg}; 50848b8605Smrg 51848b8605Smrg/** 52848b8605Smrg * Create a VdpVideoSurface. 53848b8605Smrg */ 54848b8605SmrgVdpStatus 55848b8605SmrgvlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type, 56848b8605Smrg uint32_t width, uint32_t height, 57848b8605Smrg VdpVideoSurface *surface) 58848b8605Smrg{ 59848b8605Smrg struct pipe_context *pipe; 60848b8605Smrg vlVdpSurface *p_surf; 61848b8605Smrg VdpStatus ret; 62848b8605Smrg 63848b8605Smrg if (!(width && height)) { 64848b8605Smrg ret = VDP_STATUS_INVALID_SIZE; 65848b8605Smrg goto inv_size; 66848b8605Smrg } 67848b8605Smrg 68848b8605Smrg p_surf = CALLOC(1, sizeof(vlVdpSurface)); 69848b8605Smrg if (!p_surf) { 70848b8605Smrg ret = VDP_STATUS_RESOURCES; 71848b8605Smrg goto no_res; 72848b8605Smrg } 73848b8605Smrg 74848b8605Smrg vlVdpDevice *dev = vlGetDataHTAB(device); 75848b8605Smrg if (!dev) { 76848b8605Smrg ret = VDP_STATUS_INVALID_HANDLE; 77848b8605Smrg goto inv_device; 78848b8605Smrg } 79848b8605Smrg 80848b8605Smrg DeviceReference(&p_surf->device, dev); 81848b8605Smrg pipe = dev->context; 82848b8605Smrg 83b8e80941Smrg mtx_lock(&dev->mutex); 84848b8605Smrg memset(&p_surf->templat, 0, sizeof(p_surf->templat)); 85848b8605Smrg p_surf->templat.buffer_format = pipe->screen->get_video_param 86848b8605Smrg ( 87848b8605Smrg pipe->screen, 88848b8605Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 89848b8605Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 90848b8605Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT 91848b8605Smrg ); 92848b8605Smrg p_surf->templat.chroma_format = ChromaToPipe(chroma_type); 93848b8605Smrg p_surf->templat.width = width; 94848b8605Smrg p_surf->templat.height = height; 95848b8605Smrg p_surf->templat.interlaced = pipe->screen->get_video_param 96848b8605Smrg ( 97848b8605Smrg pipe->screen, 98848b8605Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 99848b8605Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 100848b8605Smrg PIPE_VIDEO_CAP_PREFERS_INTERLACED 101848b8605Smrg ); 102848b8605Smrg if (p_surf->templat.buffer_format != PIPE_FORMAT_NONE) 103848b8605Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 104848b8605Smrg 105848b8605Smrg /* do not mandate early allocation of a video buffer */ 106848b8605Smrg vlVdpVideoSurfaceClear(p_surf); 107b8e80941Smrg mtx_unlock(&dev->mutex); 108848b8605Smrg 109848b8605Smrg *surface = vlAddDataHTAB(p_surf); 110848b8605Smrg if (*surface == 0) { 111848b8605Smrg ret = VDP_STATUS_ERROR; 112848b8605Smrg goto no_handle; 113848b8605Smrg } 114848b8605Smrg 115848b8605Smrg return VDP_STATUS_OK; 116848b8605Smrg 117848b8605Smrgno_handle: 118848b8605Smrg p_surf->video_buffer->destroy(p_surf->video_buffer); 119848b8605Smrg 120848b8605Smrginv_device: 121848b8605Smrg DeviceReference(&p_surf->device, NULL); 122848b8605Smrg FREE(p_surf); 123848b8605Smrg 124848b8605Smrgno_res: 125848b8605Smrginv_size: 126848b8605Smrg return ret; 127848b8605Smrg} 128848b8605Smrg 129848b8605Smrg/** 130848b8605Smrg * Destroy a VdpVideoSurface. 131848b8605Smrg */ 132848b8605SmrgVdpStatus 133848b8605SmrgvlVdpVideoSurfaceDestroy(VdpVideoSurface surface) 134848b8605Smrg{ 135848b8605Smrg vlVdpSurface *p_surf; 136848b8605Smrg 137848b8605Smrg p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface); 138848b8605Smrg if (!p_surf) 139848b8605Smrg return VDP_STATUS_INVALID_HANDLE; 140848b8605Smrg 141b8e80941Smrg mtx_lock(&p_surf->device->mutex); 142848b8605Smrg if (p_surf->video_buffer) 143848b8605Smrg p_surf->video_buffer->destroy(p_surf->video_buffer); 144b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 145848b8605Smrg 146848b8605Smrg vlRemoveDataHTAB(surface); 147848b8605Smrg DeviceReference(&p_surf->device, NULL); 148848b8605Smrg FREE(p_surf); 149848b8605Smrg 150848b8605Smrg return VDP_STATUS_OK; 151848b8605Smrg} 152848b8605Smrg 153848b8605Smrg/** 154848b8605Smrg * Retrieve the parameters used to create a VdpVideoSurface. 155848b8605Smrg */ 156848b8605SmrgVdpStatus 157848b8605SmrgvlVdpVideoSurfaceGetParameters(VdpVideoSurface surface, 158848b8605Smrg VdpChromaType *chroma_type, 159848b8605Smrg uint32_t *width, uint32_t *height) 160848b8605Smrg{ 161848b8605Smrg if (!(width && height && chroma_type)) 162848b8605Smrg return VDP_STATUS_INVALID_POINTER; 163848b8605Smrg 164848b8605Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 165848b8605Smrg if (!p_surf) 166848b8605Smrg return VDP_STATUS_INVALID_HANDLE; 167848b8605Smrg 168848b8605Smrg if (p_surf->video_buffer) { 169848b8605Smrg *width = p_surf->video_buffer->width; 170848b8605Smrg *height = p_surf->video_buffer->height; 171848b8605Smrg *chroma_type = PipeToChroma(p_surf->video_buffer->chroma_format); 172848b8605Smrg } else { 173848b8605Smrg *width = p_surf->templat.width; 174848b8605Smrg *height = p_surf->templat.height; 175848b8605Smrg *chroma_type = PipeToChroma(p_surf->templat.chroma_format); 176848b8605Smrg } 177848b8605Smrg 178848b8605Smrg return VDP_STATUS_OK; 179848b8605Smrg} 180848b8605Smrg 181848b8605Smrgstatic void 182848b8605SmrgvlVdpVideoSurfaceSize(vlVdpSurface *p_surf, int component, 183848b8605Smrg unsigned *width, unsigned *height) 184848b8605Smrg{ 185848b8605Smrg *width = p_surf->templat.width; 186848b8605Smrg *height = p_surf->templat.height; 187848b8605Smrg 188b8e80941Smrg vl_video_buffer_adjust_size(width, height, component, 189b8e80941Smrg p_surf->templat.chroma_format, 190b8e80941Smrg p_surf->templat.interlaced); 191848b8605Smrg} 192848b8605Smrg 193848b8605Smrg/** 194848b8605Smrg * Copy image data from a VdpVideoSurface to application memory in a specified 195848b8605Smrg * YCbCr format. 196848b8605Smrg */ 197848b8605SmrgVdpStatus 198848b8605SmrgvlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, 199848b8605Smrg VdpYCbCrFormat destination_ycbcr_format, 200848b8605Smrg void *const *destination_data, 201848b8605Smrg uint32_t const *destination_pitches) 202848b8605Smrg{ 203848b8605Smrg vlVdpSurface *vlsurface; 204848b8605Smrg struct pipe_context *pipe; 205848b8605Smrg enum pipe_format format, buffer_format; 206848b8605Smrg struct pipe_sampler_view **sampler_views; 207848b8605Smrg enum getbits_conversion conversion = CONVERSION_NONE; 208848b8605Smrg unsigned i, j; 209848b8605Smrg 210848b8605Smrg vlsurface = vlGetDataHTAB(surface); 211848b8605Smrg if (!vlsurface) 212848b8605Smrg return VDP_STATUS_INVALID_HANDLE; 213848b8605Smrg 214848b8605Smrg pipe = vlsurface->device->context; 215848b8605Smrg if (!pipe) 216848b8605Smrg return VDP_STATUS_INVALID_HANDLE; 217848b8605Smrg 218b8e80941Smrg if (!destination_data || !destination_pitches) 219b8e80941Smrg return VDP_STATUS_INVALID_POINTER; 220b8e80941Smrg 221848b8605Smrg format = FormatYCBCRToPipe(destination_ycbcr_format); 222848b8605Smrg if (format == PIPE_FORMAT_NONE) 223848b8605Smrg return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; 224848b8605Smrg 225848b8605Smrg if (vlsurface->video_buffer == NULL) 226848b8605Smrg return VDP_STATUS_INVALID_VALUE; 227848b8605Smrg 228848b8605Smrg buffer_format = vlsurface->video_buffer->buffer_format; 229848b8605Smrg if (format != buffer_format) { 230848b8605Smrg if (format == PIPE_FORMAT_YV12 && buffer_format == PIPE_FORMAT_NV12) 231848b8605Smrg conversion = CONVERSION_NV12_TO_YV12; 232848b8605Smrg else if (format == PIPE_FORMAT_NV12 && buffer_format == PIPE_FORMAT_YV12) 233848b8605Smrg conversion = CONVERSION_YV12_TO_NV12; 234848b8605Smrg else if ((format == PIPE_FORMAT_YUYV && buffer_format == PIPE_FORMAT_UYVY) || 235848b8605Smrg (format == PIPE_FORMAT_UYVY && buffer_format == PIPE_FORMAT_YUYV)) 236848b8605Smrg conversion = CONVERSION_SWAP_YUYV_UYVY; 237848b8605Smrg else 238848b8605Smrg return VDP_STATUS_NO_IMPLEMENTATION; 239848b8605Smrg } 240848b8605Smrg 241b8e80941Smrg mtx_lock(&vlsurface->device->mutex); 242848b8605Smrg sampler_views = vlsurface->video_buffer->get_sampler_view_planes(vlsurface->video_buffer); 243848b8605Smrg if (!sampler_views) { 244b8e80941Smrg mtx_unlock(&vlsurface->device->mutex); 245848b8605Smrg return VDP_STATUS_RESOURCES; 246848b8605Smrg } 247848b8605Smrg 248848b8605Smrg for (i = 0; i < 3; ++i) { 249848b8605Smrg unsigned width, height; 250848b8605Smrg struct pipe_sampler_view *sv = sampler_views[i]; 251848b8605Smrg if (!sv) continue; 252848b8605Smrg 253848b8605Smrg vlVdpVideoSurfaceSize(vlsurface, i, &width, &height); 254848b8605Smrg 255848b8605Smrg for (j = 0; j < sv->texture->array_size; ++j) { 256848b8605Smrg struct pipe_box box = { 257848b8605Smrg 0, 0, j, 258848b8605Smrg width, height, 1 259848b8605Smrg }; 260848b8605Smrg struct pipe_transfer *transfer; 261848b8605Smrg uint8_t *map; 262848b8605Smrg 263848b8605Smrg map = pipe->transfer_map(pipe, sv->texture, 0, 264848b8605Smrg PIPE_TRANSFER_READ, &box, &transfer); 265848b8605Smrg if (!map) { 266b8e80941Smrg mtx_unlock(&vlsurface->device->mutex); 267848b8605Smrg return VDP_STATUS_RESOURCES; 268848b8605Smrg } 269848b8605Smrg 270848b8605Smrg if (conversion == CONVERSION_NV12_TO_YV12 && i == 1) { 271b8e80941Smrg u_copy_nv12_to_yv12(destination_data, destination_pitches, 272848b8605Smrg i, j, transfer->stride, sv->texture->array_size, 273848b8605Smrg map, box.width, box.height); 274848b8605Smrg } else if (conversion == CONVERSION_YV12_TO_NV12 && i > 0) { 275b8e80941Smrg u_copy_yv12_to_nv12(destination_data, destination_pitches, 276848b8605Smrg i, j, transfer->stride, sv->texture->array_size, 277848b8605Smrg map, box.width, box.height); 278848b8605Smrg } else if (conversion == CONVERSION_SWAP_YUYV_UYVY) { 279b8e80941Smrg u_copy_swap422_packed(destination_data, destination_pitches, 280848b8605Smrg i, j, transfer->stride, sv->texture->array_size, 281848b8605Smrg map, box.width, box.height); 282848b8605Smrg } else { 283848b8605Smrg util_copy_rect(destination_data[i] + destination_pitches[i] * j, sv->texture->format, 284848b8605Smrg destination_pitches[i] * sv->texture->array_size, 0, 0, 285848b8605Smrg box.width, box.height, map, transfer->stride, 0, 0); 286848b8605Smrg } 287848b8605Smrg 288848b8605Smrg pipe_transfer_unmap(pipe, transfer); 289848b8605Smrg } 290848b8605Smrg } 291b8e80941Smrg mtx_unlock(&vlsurface->device->mutex); 292848b8605Smrg 293848b8605Smrg return VDP_STATUS_OK; 294848b8605Smrg} 295848b8605Smrg 296848b8605Smrg/** 297848b8605Smrg * Copy image data from application memory in a specific YCbCr format to 298848b8605Smrg * a VdpVideoSurface. 299848b8605Smrg */ 300848b8605SmrgVdpStatus 301848b8605SmrgvlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface, 302848b8605Smrg VdpYCbCrFormat source_ycbcr_format, 303848b8605Smrg void const *const *source_data, 304848b8605Smrg uint32_t const *source_pitches) 305848b8605Smrg{ 306848b8605Smrg enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format); 307b8e80941Smrg enum getbits_conversion conversion = CONVERSION_NONE; 308848b8605Smrg struct pipe_context *pipe; 309848b8605Smrg struct pipe_sampler_view **sampler_views; 310848b8605Smrg unsigned i, j; 311b8e80941Smrg unsigned usage = PIPE_TRANSFER_WRITE; 312848b8605Smrg 313848b8605Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 314848b8605Smrg if (!p_surf) 315848b8605Smrg return VDP_STATUS_INVALID_HANDLE; 316848b8605Smrg 317848b8605Smrg pipe = p_surf->device->context; 318848b8605Smrg if (!pipe) 319848b8605Smrg return VDP_STATUS_INVALID_HANDLE; 320848b8605Smrg 321b8e80941Smrg if (!source_data || !source_pitches) 322b8e80941Smrg return VDP_STATUS_INVALID_POINTER; 323b8e80941Smrg 324b8e80941Smrg mtx_lock(&p_surf->device->mutex); 325b8e80941Smrg 326b8e80941Smrg if (p_surf->video_buffer == NULL || 327b8e80941Smrg ((pformat != p_surf->video_buffer->buffer_format))) { 328b8e80941Smrg enum pipe_format nformat = pformat; 329b8e80941Smrg struct pipe_screen *screen = pipe->screen; 330b8e80941Smrg 331b8e80941Smrg /* Determine the most suitable format for the new surface */ 332b8e80941Smrg if (!screen->is_video_format_supported(screen, nformat, 333b8e80941Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 334b8e80941Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) { 335b8e80941Smrg nformat = screen->get_video_param(screen, 336b8e80941Smrg PIPE_VIDEO_PROFILE_UNKNOWN, 337b8e80941Smrg PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 338b8e80941Smrg PIPE_VIDEO_CAP_PREFERED_FORMAT); 339b8e80941Smrg if (nformat == PIPE_FORMAT_NONE) { 340b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 341b8e80941Smrg return VDP_STATUS_NO_IMPLEMENTATION; 342b8e80941Smrg } 343b8e80941Smrg } 344848b8605Smrg 345b8e80941Smrg if (p_surf->video_buffer == NULL || 346b8e80941Smrg nformat != p_surf->video_buffer->buffer_format) { 347b8e80941Smrg /* destroy the old one */ 348b8e80941Smrg if (p_surf->video_buffer) 349b8e80941Smrg p_surf->video_buffer->destroy(p_surf->video_buffer); 350848b8605Smrg 351b8e80941Smrg /* adjust the template parameters */ 352b8e80941Smrg p_surf->templat.buffer_format = nformat; 353b8e80941Smrg if (nformat == PIPE_FORMAT_YUYV || nformat == PIPE_FORMAT_UYVY) 354b8e80941Smrg p_surf->templat.interlaced = false; 355848b8605Smrg 356b8e80941Smrg /* and try to create the video buffer with the new format */ 357b8e80941Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 358b8e80941Smrg 359b8e80941Smrg /* stil no luck? ok forget it we don't support it */ 360b8e80941Smrg if (!p_surf->video_buffer) { 361b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 362b8e80941Smrg return VDP_STATUS_NO_IMPLEMENTATION; 363b8e80941Smrg } 364b8e80941Smrg vlVdpVideoSurfaceClear(p_surf); 365b8e80941Smrg } 366b8e80941Smrg } 367848b8605Smrg 368b8e80941Smrg if (pformat != p_surf->video_buffer->buffer_format) { 369b8e80941Smrg if (pformat == PIPE_FORMAT_YV12 && 370b8e80941Smrg p_surf->video_buffer->buffer_format == PIPE_FORMAT_NV12) 371b8e80941Smrg conversion = CONVERSION_YV12_TO_NV12; 372b8e80941Smrg else { 373b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 374848b8605Smrg return VDP_STATUS_NO_IMPLEMENTATION; 375848b8605Smrg } 376848b8605Smrg } 377848b8605Smrg 378848b8605Smrg sampler_views = p_surf->video_buffer->get_sampler_view_planes(p_surf->video_buffer); 379848b8605Smrg if (!sampler_views) { 380b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 381848b8605Smrg return VDP_STATUS_RESOURCES; 382848b8605Smrg } 383848b8605Smrg 384848b8605Smrg for (i = 0; i < 3; ++i) { 385848b8605Smrg unsigned width, height; 386848b8605Smrg struct pipe_sampler_view *sv = sampler_views[i]; 387b8e80941Smrg struct pipe_resource *tex; 388848b8605Smrg if (!sv || !source_pitches[i]) continue; 389848b8605Smrg 390b8e80941Smrg tex = sv->texture; 391848b8605Smrg vlVdpVideoSurfaceSize(p_surf, i, &width, &height); 392848b8605Smrg 393b8e80941Smrg for (j = 0; j < tex->array_size; ++j) { 394848b8605Smrg struct pipe_box dst_box = { 395848b8605Smrg 0, 0, j, 396848b8605Smrg width, height, 1 397848b8605Smrg }; 398848b8605Smrg 399b8e80941Smrg if (conversion == CONVERSION_YV12_TO_NV12 && i == 1) { 400b8e80941Smrg struct pipe_transfer *transfer; 401b8e80941Smrg uint8_t *map; 402b8e80941Smrg 403b8e80941Smrg map = pipe->transfer_map(pipe, tex, 0, usage, 404b8e80941Smrg &dst_box, &transfer); 405b8e80941Smrg if (!map) { 406b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 407b8e80941Smrg return VDP_STATUS_RESOURCES; 408b8e80941Smrg } 409b8e80941Smrg 410b8e80941Smrg u_copy_nv12_from_yv12(source_data, source_pitches, 411b8e80941Smrg i, j, transfer->stride, tex->array_size, 412b8e80941Smrg map, dst_box.width, dst_box.height); 413b8e80941Smrg 414b8e80941Smrg pipe_transfer_unmap(pipe, transfer); 415b8e80941Smrg } else { 416b8e80941Smrg pipe->texture_subdata(pipe, tex, 0, 417b8e80941Smrg PIPE_TRANSFER_WRITE, &dst_box, 418b8e80941Smrg source_data[i] + source_pitches[i] * j, 419b8e80941Smrg source_pitches[i] * tex->array_size, 420b8e80941Smrg 0); 421b8e80941Smrg } 422b8e80941Smrg /* 423b8e80941Smrg * This surface has already been synced 424b8e80941Smrg * by the first map. 425b8e80941Smrg */ 426b8e80941Smrg usage |= PIPE_TRANSFER_UNSYNCHRONIZED; 427848b8605Smrg } 428848b8605Smrg } 429b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 430848b8605Smrg 431848b8605Smrg return VDP_STATUS_OK; 432848b8605Smrg} 433848b8605Smrg 434848b8605Smrg/** 435848b8605Smrg * Helper function to initially clear the VideoSurface after (re-)creation 436848b8605Smrg */ 437848b8605Smrgvoid 438848b8605SmrgvlVdpVideoSurfaceClear(vlVdpSurface *vlsurf) 439848b8605Smrg{ 440848b8605Smrg struct pipe_context *pipe = vlsurf->device->context; 441848b8605Smrg struct pipe_surface **surfaces; 442848b8605Smrg unsigned i; 443848b8605Smrg 444848b8605Smrg if (!vlsurf->video_buffer) 445848b8605Smrg return; 446848b8605Smrg 447848b8605Smrg surfaces = vlsurf->video_buffer->get_surfaces(vlsurf->video_buffer); 448848b8605Smrg for (i = 0; i < VL_MAX_SURFACES; ++i) { 449848b8605Smrg union pipe_color_union c = {}; 450848b8605Smrg 451848b8605Smrg if (!surfaces[i]) 452848b8605Smrg continue; 453848b8605Smrg 454848b8605Smrg if (i > !!vlsurf->templat.interlaced) 455848b8605Smrg c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; 456848b8605Smrg 457848b8605Smrg pipe->clear_render_target(pipe, surfaces[i], &c, 0, 0, 458b8e80941Smrg surfaces[i]->width, surfaces[i]->height, false); 459848b8605Smrg } 460848b8605Smrg pipe->flush(pipe, NULL, 0); 461848b8605Smrg} 462848b8605Smrg 463848b8605Smrg/** 464848b8605Smrg * Interop to mesa state tracker 465848b8605Smrg */ 466848b8605Smrgstruct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface) 467848b8605Smrg{ 468848b8605Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 469848b8605Smrg if (!p_surf) 470848b8605Smrg return NULL; 471848b8605Smrg 472b8e80941Smrg mtx_lock(&p_surf->device->mutex); 473848b8605Smrg if (p_surf->video_buffer == NULL) { 474848b8605Smrg struct pipe_context *pipe = p_surf->device->context; 475848b8605Smrg 476848b8605Smrg /* try to create a video buffer if we don't already have one */ 477848b8605Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 478848b8605Smrg } 479b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 480848b8605Smrg 481848b8605Smrg return p_surf->video_buffer; 482848b8605Smrg} 483b8e80941Smrg 484b8e80941SmrgVdpStatus vlVdpVideoSurfaceDMABuf(VdpVideoSurface surface, 485b8e80941Smrg VdpVideoSurfacePlane plane, 486b8e80941Smrg struct VdpSurfaceDMABufDesc *result) 487b8e80941Smrg{ 488b8e80941Smrg vlVdpSurface *p_surf = vlGetDataHTAB(surface); 489b8e80941Smrg 490b8e80941Smrg struct pipe_screen *pscreen; 491b8e80941Smrg struct winsys_handle whandle; 492b8e80941Smrg 493b8e80941Smrg struct pipe_surface *surf; 494b8e80941Smrg 495b8e80941Smrg if (!p_surf) 496b8e80941Smrg return VDP_STATUS_INVALID_HANDLE; 497b8e80941Smrg 498b8e80941Smrg if (plane > 3) 499b8e80941Smrg return VDP_STATUS_INVALID_VALUE; 500b8e80941Smrg 501b8e80941Smrg if (!result) 502b8e80941Smrg return VDP_STATUS_INVALID_POINTER; 503b8e80941Smrg 504b8e80941Smrg memset(result, 0, sizeof(*result)); 505b8e80941Smrg result->handle = -1; 506b8e80941Smrg 507b8e80941Smrg mtx_lock(&p_surf->device->mutex); 508b8e80941Smrg if (p_surf->video_buffer == NULL) { 509b8e80941Smrg struct pipe_context *pipe = p_surf->device->context; 510b8e80941Smrg 511b8e80941Smrg /* try to create a video buffer if we don't already have one */ 512b8e80941Smrg p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); 513b8e80941Smrg } 514b8e80941Smrg 515b8e80941Smrg /* Check if surface match interop requirements */ 516b8e80941Smrg if (p_surf->video_buffer == NULL || !p_surf->video_buffer->interlaced || 517b8e80941Smrg p_surf->video_buffer->buffer_format != PIPE_FORMAT_NV12) { 518b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 519b8e80941Smrg return VDP_STATUS_NO_IMPLEMENTATION; 520b8e80941Smrg } 521b8e80941Smrg 522b8e80941Smrg surf = p_surf->video_buffer->get_surfaces(p_surf->video_buffer)[plane]; 523b8e80941Smrg if (!surf) { 524b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 525b8e80941Smrg return VDP_STATUS_RESOURCES; 526b8e80941Smrg } 527b8e80941Smrg 528b8e80941Smrg memset(&whandle, 0, sizeof(struct winsys_handle)); 529b8e80941Smrg whandle.type = WINSYS_HANDLE_TYPE_FD; 530b8e80941Smrg whandle.layer = surf->u.tex.first_layer; 531b8e80941Smrg 532b8e80941Smrg pscreen = surf->texture->screen; 533b8e80941Smrg if (!pscreen->resource_get_handle(pscreen, p_surf->device->context, 534b8e80941Smrg surf->texture, &whandle, 535b8e80941Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { 536b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 537b8e80941Smrg return VDP_STATUS_NO_IMPLEMENTATION; 538b8e80941Smrg } 539b8e80941Smrg 540b8e80941Smrg mtx_unlock(&p_surf->device->mutex); 541b8e80941Smrg 542b8e80941Smrg result->handle = whandle.handle; 543b8e80941Smrg result->width = surf->width; 544b8e80941Smrg result->height = surf->height; 545b8e80941Smrg result->offset = whandle.offset; 546b8e80941Smrg result->stride = whandle.stride; 547b8e80941Smrg 548b8e80941Smrg if (surf->format == PIPE_FORMAT_R8_UNORM) 549b8e80941Smrg result->format = VDP_RGBA_FORMAT_R8; 550b8e80941Smrg else 551b8e80941Smrg result->format = VDP_RGBA_FORMAT_R8G8; 552b8e80941Smrg 553b8e80941Smrg return VDP_STATUS_OK; 554b8e80941Smrg} 555