1af69d88dSmrg/************************************************************************** 2af69d88dSmrg * 3af69d88dSmrg * Copyright 2013 Advanced Micro Devices, Inc. 4af69d88dSmrg * All Rights Reserved. 5af69d88dSmrg * 6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 7af69d88dSmrg * copy of this software and associated documentation files (the 8af69d88dSmrg * "Software"), to deal in the Software without restriction, including 9af69d88dSmrg * without limitation the rights to use, copy, modify, merge, publish, 10af69d88dSmrg * distribute, sub license, and/or sell copies of the Software, and to 11af69d88dSmrg * permit persons to whom the Software is furnished to do so, subject to 12af69d88dSmrg * the following conditions: 13af69d88dSmrg * 14af69d88dSmrg * The above copyright notice and this permission notice (including the 15af69d88dSmrg * next paragraph) shall be included in all copies or substantial portions 16af69d88dSmrg * of the Software. 17af69d88dSmrg * 18af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20af69d88dSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22af69d88dSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23af69d88dSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24af69d88dSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25af69d88dSmrg * 26af69d88dSmrg **************************************************************************/ 27af69d88dSmrg 28af69d88dSmrg/* 29af69d88dSmrg * Authors: 30af69d88dSmrg * Christian König <christian.koenig@amd.com> 31af69d88dSmrg * 32af69d88dSmrg */ 33af69d88dSmrg 3401e04c3fSmrg#ifdef HAVE_ST_VDPAU 3501e04c3fSmrg 36af69d88dSmrg#include "main/texobj.h" 37af69d88dSmrg#include "main/teximage.h" 38af69d88dSmrg#include "main/errors.h" 39af69d88dSmrg#include "program/prog_instruction.h" 40af69d88dSmrg 41af69d88dSmrg#include "pipe/p_state.h" 42af69d88dSmrg#include "pipe/p_video_codec.h" 43af69d88dSmrg 44af69d88dSmrg#include "util/u_inlines.h" 45af69d88dSmrg 46af69d88dSmrg#include "st_vdpau.h" 47af69d88dSmrg#include "st_context.h" 4801e04c3fSmrg#include "st_sampler_view.h" 49af69d88dSmrg#include "st_texture.h" 50af69d88dSmrg#include "st_format.h" 51af69d88dSmrg#include "st_cb_flush.h" 52af69d88dSmrg 537ec681f3Smrg#include "frontend/vdpau_interop.h" 547ec681f3Smrg#include "frontend/vdpau_dmabuf.h" 557ec681f3Smrg#include "frontend/vdpau_funcs.h" 567ec681f3Smrg#include "frontend/drm_driver.h" 577ec681f3Smrg 587ec681f3Smrg#include "drm-uapi/drm_fourcc.h" 5901e04c3fSmrg 6001e04c3fSmrgstatic struct pipe_resource * 6101e04c3fSmrgst_vdpau_video_surface_gallium(struct gl_context *ctx, const void *vdpSurface, 6201e04c3fSmrg GLuint index) 6301e04c3fSmrg{ 6401e04c3fSmrg int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 6501e04c3fSmrg uint32_t device = (uintptr_t)ctx->vdpDevice; 6601e04c3fSmrg struct pipe_sampler_view *sv; 6701e04c3fSmrg VdpVideoSurfaceGallium *f; 6801e04c3fSmrg 6901e04c3fSmrg struct pipe_video_buffer *buffer; 7001e04c3fSmrg struct pipe_sampler_view **samplers; 7101e04c3fSmrg struct pipe_resource *res = NULL; 7201e04c3fSmrg 7301e04c3fSmrg getProcAddr = (void *)ctx->vdpGetProcAddress; 7401e04c3fSmrg if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) 7501e04c3fSmrg return NULL; 7601e04c3fSmrg 7701e04c3fSmrg buffer = f((uintptr_t)vdpSurface); 7801e04c3fSmrg if (!buffer) 7901e04c3fSmrg return NULL; 8001e04c3fSmrg 8101e04c3fSmrg samplers = buffer->get_sampler_view_planes(buffer); 8201e04c3fSmrg if (!samplers) 8301e04c3fSmrg return NULL; 8401e04c3fSmrg 8501e04c3fSmrg sv = samplers[index >> 1]; 8601e04c3fSmrg if (!sv) 8701e04c3fSmrg return NULL; 8801e04c3fSmrg 8901e04c3fSmrg pipe_resource_reference(&res, sv->texture); 9001e04c3fSmrg return res; 9101e04c3fSmrg} 9201e04c3fSmrg 9301e04c3fSmrgstatic struct pipe_resource * 9401e04c3fSmrgst_vdpau_output_surface_gallium(struct gl_context *ctx, const void *vdpSurface) 9501e04c3fSmrg{ 9601e04c3fSmrg int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 9701e04c3fSmrg uint32_t device = (uintptr_t)ctx->vdpDevice; 9801e04c3fSmrg struct pipe_resource *res = NULL; 9901e04c3fSmrg VdpOutputSurfaceGallium *f; 10001e04c3fSmrg 10101e04c3fSmrg getProcAddr = (void *)ctx->vdpGetProcAddress; 10201e04c3fSmrg if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) 10301e04c3fSmrg return NULL; 10401e04c3fSmrg 10501e04c3fSmrg pipe_resource_reference(&res, f((uintptr_t)vdpSurface)); 10601e04c3fSmrg return res; 10701e04c3fSmrg} 10801e04c3fSmrg 10901e04c3fSmrgstatic struct pipe_resource * 11001e04c3fSmrgst_vdpau_resource_from_description(struct gl_context *ctx, 11101e04c3fSmrg const struct VdpSurfaceDMABufDesc *desc) 11201e04c3fSmrg{ 11301e04c3fSmrg struct st_context *st = st_context(ctx); 11401e04c3fSmrg struct pipe_resource templ, *res; 11501e04c3fSmrg struct winsys_handle whandle; 11601e04c3fSmrg 11701e04c3fSmrg if (desc->handle == -1) 11801e04c3fSmrg return NULL; 11901e04c3fSmrg 12001e04c3fSmrg memset(&templ, 0, sizeof(templ)); 12101e04c3fSmrg templ.target = PIPE_TEXTURE_2D; 12201e04c3fSmrg templ.last_level = 0; 12301e04c3fSmrg templ.depth0 = 1; 12401e04c3fSmrg templ.array_size = 1; 12501e04c3fSmrg templ.width0 = desc->width; 12601e04c3fSmrg templ.height0 = desc->height; 12701e04c3fSmrg templ.format = VdpFormatRGBAToPipe(desc->format); 12801e04c3fSmrg templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 12901e04c3fSmrg templ.usage = PIPE_USAGE_DEFAULT; 13001e04c3fSmrg 13101e04c3fSmrg memset(&whandle, 0, sizeof(whandle)); 13201e04c3fSmrg whandle.type = WINSYS_HANDLE_TYPE_FD; 13301e04c3fSmrg whandle.handle = desc->handle; 1347ec681f3Smrg whandle.modifier = DRM_FORMAT_MOD_INVALID; 13501e04c3fSmrg whandle.offset = desc->offset; 13601e04c3fSmrg whandle.stride = desc->stride; 13701e04c3fSmrg 1387ec681f3Smrg res = st->screen->resource_from_handle(st->screen, &templ, &whandle, 1397ec681f3Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 14001e04c3fSmrg close(desc->handle); 14101e04c3fSmrg 14201e04c3fSmrg return res; 14301e04c3fSmrg} 14401e04c3fSmrg 14501e04c3fSmrgstatic struct pipe_resource * 14601e04c3fSmrgst_vdpau_output_surface_dma_buf(struct gl_context *ctx, const void *vdpSurface) 14701e04c3fSmrg{ 14801e04c3fSmrg int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 14901e04c3fSmrg uint32_t device = (uintptr_t)ctx->vdpDevice; 15001e04c3fSmrg 15101e04c3fSmrg struct VdpSurfaceDMABufDesc desc; 15201e04c3fSmrg VdpOutputSurfaceDMABuf *f; 15301e04c3fSmrg 15401e04c3fSmrg getProcAddr = (void *)ctx->vdpGetProcAddress; 15501e04c3fSmrg if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF, (void**)&f)) 15601e04c3fSmrg return NULL; 15701e04c3fSmrg 15801e04c3fSmrg if (f((uintptr_t)vdpSurface, &desc) != VDP_STATUS_OK) 15901e04c3fSmrg return NULL; 16001e04c3fSmrg 16101e04c3fSmrg return st_vdpau_resource_from_description(ctx, &desc); 16201e04c3fSmrg} 16301e04c3fSmrg 16401e04c3fSmrgstatic struct pipe_resource * 16501e04c3fSmrgst_vdpau_video_surface_dma_buf(struct gl_context *ctx, const void *vdpSurface, 16601e04c3fSmrg GLuint index) 16701e04c3fSmrg{ 16801e04c3fSmrg int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 16901e04c3fSmrg uint32_t device = (uintptr_t)ctx->vdpDevice; 17001e04c3fSmrg 17101e04c3fSmrg struct VdpSurfaceDMABufDesc desc; 17201e04c3fSmrg VdpVideoSurfaceDMABuf *f; 17301e04c3fSmrg 17401e04c3fSmrg getProcAddr = (void *)ctx->vdpGetProcAddress; 17501e04c3fSmrg if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF, (void**)&f)) 17601e04c3fSmrg return NULL; 17701e04c3fSmrg 17801e04c3fSmrg if (f((uintptr_t)vdpSurface, index, &desc) != VDP_STATUS_OK) 17901e04c3fSmrg return NULL; 18001e04c3fSmrg 18101e04c3fSmrg return st_vdpau_resource_from_description(ctx, &desc); 18201e04c3fSmrg} 18301e04c3fSmrg 184af69d88dSmrgstatic void 185af69d88dSmrgst_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, 186af69d88dSmrg GLboolean output, struct gl_texture_object *texObj, 187af69d88dSmrg struct gl_texture_image *texImage, 18801e04c3fSmrg const void *vdpSurface, GLuint index) 189af69d88dSmrg{ 190af69d88dSmrg struct st_context *st = st_context(ctx); 1917ec681f3Smrg struct pipe_screen *screen = st->screen; 192af69d88dSmrg struct st_texture_object *stObj = st_texture_object(texObj); 193af69d88dSmrg struct st_texture_image *stImage = st_texture_image(texImage); 19401e04c3fSmrg 195af69d88dSmrg struct pipe_resource *res; 196af69d88dSmrg mesa_format texFormat; 1977ec681f3Smrg int layer_override = -1; 198af69d88dSmrg 199af69d88dSmrg if (output) { 20001e04c3fSmrg res = st_vdpau_output_surface_dma_buf(ctx, vdpSurface); 201af69d88dSmrg 20201e04c3fSmrg if (!res) 20301e04c3fSmrg res = st_vdpau_output_surface_gallium(ctx, vdpSurface); 204af69d88dSmrg 205af69d88dSmrg } else { 20601e04c3fSmrg res = st_vdpau_video_surface_dma_buf(ctx, vdpSurface, index); 207af69d88dSmrg 20801e04c3fSmrg if (!res) { 20901e04c3fSmrg res = st_vdpau_video_surface_gallium(ctx, vdpSurface, index); 21001e04c3fSmrg layer_override = index & 1; 211af69d88dSmrg } 212af69d88dSmrg } 213af69d88dSmrg 2147ec681f3Smrg /* If the resource is from a different screen, try re-importing it */ 2157ec681f3Smrg if (res && res->screen != screen) { 2167ec681f3Smrg struct pipe_resource *new_res = NULL; 2177ec681f3Smrg struct winsys_handle whandle = { .type = WINSYS_HANDLE_TYPE_FD }; 2187ec681f3Smrg unsigned usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 2197ec681f3Smrg 2207ec681f3Smrg if (screen->get_param(screen, PIPE_CAP_DMABUF) && 2217ec681f3Smrg res->screen->get_param(res->screen, PIPE_CAP_DMABUF) && 2227ec681f3Smrg res->screen->resource_get_handle(res->screen, NULL, res, &whandle, 2237ec681f3Smrg usage)) { 2247ec681f3Smrg whandle.modifier = DRM_FORMAT_MOD_INVALID; 2257ec681f3Smrg new_res = screen->resource_from_handle(screen, res, &whandle, usage); 2267ec681f3Smrg close(whandle.handle); 2277ec681f3Smrg } 2287ec681f3Smrg 2297ec681f3Smrg pipe_resource_reference(&res, NULL); 2307ec681f3Smrg res = new_res; 231af69d88dSmrg } 232af69d88dSmrg 2337ec681f3Smrg if (!res) { 234af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); 235af69d88dSmrg return; 236af69d88dSmrg } 237af69d88dSmrg 238af69d88dSmrg /* switch to surface based */ 239af69d88dSmrg if (!stObj->surface_based) { 24001e04c3fSmrg _mesa_clear_texture_object(ctx, texObj, NULL); 241af69d88dSmrg stObj->surface_based = GL_TRUE; 242af69d88dSmrg } 243af69d88dSmrg 244af69d88dSmrg texFormat = st_pipe_format_to_mesa_format(res->format); 245af69d88dSmrg 246af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, 247af69d88dSmrg res->width0, res->height0, 1, 0, GL_RGBA, 248af69d88dSmrg texFormat); 249af69d88dSmrg 250af69d88dSmrg pipe_resource_reference(&stObj->pt, res); 251af69d88dSmrg st_texture_release_all_sampler_views(st, stObj); 252af69d88dSmrg pipe_resource_reference(&stImage->pt, res); 253af69d88dSmrg 254af69d88dSmrg stObj->surface_format = res->format; 2557ec681f3Smrg stObj->level_override = -1; 25601e04c3fSmrg stObj->layer_override = layer_override; 257af69d88dSmrg 258af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 25901e04c3fSmrg pipe_resource_reference(&res, NULL); 260af69d88dSmrg} 261af69d88dSmrg 262af69d88dSmrgstatic void 263af69d88dSmrgst_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access, 264af69d88dSmrg GLboolean output, struct gl_texture_object *texObj, 265af69d88dSmrg struct gl_texture_image *texImage, 26601e04c3fSmrg const void *vdpSurface, GLuint index) 267af69d88dSmrg{ 268af69d88dSmrg struct st_context *st = st_context(ctx); 269af69d88dSmrg struct st_texture_object *stObj = st_texture_object(texObj); 270af69d88dSmrg struct st_texture_image *stImage = st_texture_image(texImage); 271af69d88dSmrg 272af69d88dSmrg pipe_resource_reference(&stObj->pt, NULL); 273af69d88dSmrg st_texture_release_all_sampler_views(st, stObj); 274af69d88dSmrg pipe_resource_reference(&stImage->pt, NULL); 275af69d88dSmrg 2767ec681f3Smrg stObj->level_override = -1; 2777ec681f3Smrg stObj->layer_override = -1; 27801e04c3fSmrg 279af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 280af69d88dSmrg 28101e04c3fSmrg /* NV_vdpau_interop does not specify an explicit synchronization mechanism 28201e04c3fSmrg * between the GL and VDPAU contexts. Provide automatic synchronization here. 28301e04c3fSmrg */ 284af69d88dSmrg st_flush(st, NULL, 0); 285af69d88dSmrg} 286af69d88dSmrg 287af69d88dSmrgvoid 288af69d88dSmrgst_init_vdpau_functions(struct dd_function_table *functions) 289af69d88dSmrg{ 290af69d88dSmrg functions->VDPAUMapSurface = st_vdpau_map_surface; 291af69d88dSmrg functions->VDPAUUnmapSurface = st_vdpau_unmap_surface; 292af69d88dSmrg} 29301e04c3fSmrg#endif 294