1/************************************************************************** 2 * 3 * Copyright 2013 Advanced Micro Devices, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/* 29 * Authors: 30 * Christian König <christian.koenig@amd.com> 31 * 32 */ 33 34#include "main/texobj.h" 35#include "main/teximage.h" 36#include "main/errors.h" 37#include "program/prog_instruction.h" 38 39#include "pipe/p_state.h" 40#include "pipe/p_video_codec.h" 41 42#include "util/u_inlines.h" 43 44#include "st_vdpau.h" 45#include "st_context.h" 46#include "st_sampler_view.h" 47#include "st_texture.h" 48#include "st_format.h" 49#include "st_cb_flush.h" 50 51#ifdef HAVE_ST_VDPAU 52 53#include "state_tracker/vdpau_interop.h" 54#include "state_tracker/vdpau_dmabuf.h" 55#include "state_tracker/vdpau_funcs.h" 56#include "state_tracker/drm_driver.h" 57 58static struct pipe_resource * 59st_vdpau_video_surface_gallium(struct gl_context *ctx, const void *vdpSurface, 60 GLuint index) 61{ 62 int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 63 uint32_t device = (uintptr_t)ctx->vdpDevice; 64 struct pipe_sampler_view *sv; 65 VdpVideoSurfaceGallium *f; 66 67 struct pipe_video_buffer *buffer; 68 struct pipe_sampler_view **samplers; 69 struct pipe_resource *res = NULL; 70 71 getProcAddr = (void *)ctx->vdpGetProcAddress; 72 if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) 73 return NULL; 74 75 buffer = f((uintptr_t)vdpSurface); 76 if (!buffer) 77 return NULL; 78 79 samplers = buffer->get_sampler_view_planes(buffer); 80 if (!samplers) 81 return NULL; 82 83 sv = samplers[index >> 1]; 84 if (!sv) 85 return NULL; 86 87 pipe_resource_reference(&res, sv->texture); 88 return res; 89} 90 91static struct pipe_resource * 92st_vdpau_output_surface_gallium(struct gl_context *ctx, const void *vdpSurface) 93{ 94 int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 95 uint32_t device = (uintptr_t)ctx->vdpDevice; 96 struct pipe_resource *res = NULL; 97 VdpOutputSurfaceGallium *f; 98 99 getProcAddr = (void *)ctx->vdpGetProcAddress; 100 if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) 101 return NULL; 102 103 pipe_resource_reference(&res, f((uintptr_t)vdpSurface)); 104 return res; 105} 106 107static struct pipe_resource * 108st_vdpau_resource_from_description(struct gl_context *ctx, 109 const struct VdpSurfaceDMABufDesc *desc) 110{ 111 struct st_context *st = st_context(ctx); 112 struct pipe_resource templ, *res; 113 struct winsys_handle whandle; 114 115 if (desc->handle == -1) 116 return NULL; 117 118 memset(&templ, 0, sizeof(templ)); 119 templ.target = PIPE_TEXTURE_2D; 120 templ.last_level = 0; 121 templ.depth0 = 1; 122 templ.array_size = 1; 123 templ.width0 = desc->width; 124 templ.height0 = desc->height; 125 templ.format = VdpFormatRGBAToPipe(desc->format); 126 templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 127 templ.usage = PIPE_USAGE_DEFAULT; 128 129 memset(&whandle, 0, sizeof(whandle)); 130 whandle.type = DRM_API_HANDLE_TYPE_FD; 131 whandle.handle = desc->handle; 132 whandle.offset = desc->offset; 133 whandle.stride = desc->stride; 134 135 res = st->pipe->screen->resource_from_handle(st->pipe->screen, &templ, &whandle, 136 PIPE_HANDLE_USAGE_READ_WRITE); 137 close(desc->handle); 138 139 return res; 140} 141 142static struct pipe_resource * 143st_vdpau_output_surface_dma_buf(struct gl_context *ctx, const void *vdpSurface) 144{ 145 int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 146 uint32_t device = (uintptr_t)ctx->vdpDevice; 147 148 struct VdpSurfaceDMABufDesc desc; 149 VdpOutputSurfaceDMABuf *f; 150 151 getProcAddr = (void *)ctx->vdpGetProcAddress; 152 if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF, (void**)&f)) 153 return NULL; 154 155 if (f((uintptr_t)vdpSurface, &desc) != VDP_STATUS_OK) 156 return NULL; 157 158 return st_vdpau_resource_from_description(ctx, &desc); 159} 160 161static struct pipe_resource * 162st_vdpau_video_surface_dma_buf(struct gl_context *ctx, const void *vdpSurface, 163 GLuint index) 164{ 165 int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); 166 uint32_t device = (uintptr_t)ctx->vdpDevice; 167 168 struct VdpSurfaceDMABufDesc desc; 169 VdpVideoSurfaceDMABuf *f; 170 171 getProcAddr = (void *)ctx->vdpGetProcAddress; 172 if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF, (void**)&f)) 173 return NULL; 174 175 if (f((uintptr_t)vdpSurface, index, &desc) != VDP_STATUS_OK) 176 return NULL; 177 178 return st_vdpau_resource_from_description(ctx, &desc); 179} 180 181static void 182st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, 183 GLboolean output, struct gl_texture_object *texObj, 184 struct gl_texture_image *texImage, 185 const void *vdpSurface, GLuint index) 186{ 187 struct st_context *st = st_context(ctx); 188 struct st_texture_object *stObj = st_texture_object(texObj); 189 struct st_texture_image *stImage = st_texture_image(texImage); 190 191 struct pipe_resource *res; 192 mesa_format texFormat; 193 uint layer_override = 0; 194 195 if (output) { 196 res = st_vdpau_output_surface_dma_buf(ctx, vdpSurface); 197 198 if (!res) 199 res = st_vdpau_output_surface_gallium(ctx, vdpSurface); 200 201 } else { 202 res = st_vdpau_video_surface_dma_buf(ctx, vdpSurface, index); 203 204 if (!res) { 205 res = st_vdpau_video_surface_gallium(ctx, vdpSurface, index); 206 layer_override = index & 1; 207 } 208 } 209 210 if (!res) { 211 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); 212 return; 213 } 214 215 /* do we have different screen objects ? */ 216 if (res->screen != st->pipe->screen) { 217 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); 218 pipe_resource_reference(&res, NULL); 219 return; 220 } 221 222 /* switch to surface based */ 223 if (!stObj->surface_based) { 224 _mesa_clear_texture_object(ctx, texObj); 225 stObj->surface_based = GL_TRUE; 226 } 227 228 texFormat = st_pipe_format_to_mesa_format(res->format); 229 230 _mesa_init_teximage_fields(ctx, texImage, 231 res->width0, res->height0, 1, 0, GL_RGBA, 232 texFormat); 233 234 pipe_resource_reference(&stObj->pt, res); 235 st_texture_release_all_sampler_views(st, stObj); 236 pipe_resource_reference(&stImage->pt, res); 237 238 stObj->surface_format = res->format; 239 stObj->layer_override = layer_override; 240 241 _mesa_dirty_texobj(ctx, texObj); 242 pipe_resource_reference(&res, NULL); 243} 244 245static void 246st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access, 247 GLboolean output, struct gl_texture_object *texObj, 248 struct gl_texture_image *texImage, 249 const void *vdpSurface, GLuint index) 250{ 251 struct st_context *st = st_context(ctx); 252 struct st_texture_object *stObj = st_texture_object(texObj); 253 struct st_texture_image *stImage = st_texture_image(texImage); 254 255 pipe_resource_reference(&stObj->pt, NULL); 256 st_texture_release_all_sampler_views(st, stObj); 257 pipe_resource_reference(&stImage->pt, NULL); 258 259 stObj->layer_override = 0; 260 261 _mesa_dirty_texobj(ctx, texObj); 262 263 st_flush(st, NULL, 0); 264} 265 266#endif 267 268void 269st_init_vdpau_functions(struct dd_function_table *functions) 270{ 271#ifdef HAVE_ST_VDPAU 272 functions->VDPAUMapSurface = st_vdpau_map_surface; 273 functions->VDPAUUnmapSurface = st_vdpau_unmap_surface; 274#endif 275} 276