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