Home | History | Annotate | Download | only in state_tracker
      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 Knig <christian.koenig (at) 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 
     58 static struct pipe_resource *
     59 st_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 
     91 static struct pipe_resource *
     92 st_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 
    107 static struct pipe_resource *
    108 st_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 
    142 static struct pipe_resource *
    143 st_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 
    161 static struct pipe_resource *
    162 st_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 
    181 static void
    182 st_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 
    245 static void
    246 st_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 
    268 void
    269 st_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