Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <stdbool.h>
  35. #include "util/hash_table.h"
  36. #include "util/set.h"
  37. #include "context.h"
  38. #include "glformats.h"
  39. #include "texobj.h"
  40. #include "teximage.h"
  41. #include "vdpau.h"
  42.  
  43. #define MAX_TEXTURES 4
  44.  
  45. struct vdp_surface
  46. {
  47.    GLenum target;
  48.    struct gl_texture_object *textures[MAX_TEXTURES];
  49.    GLenum access, state;
  50.    GLboolean output;
  51.    const GLvoid *vdpSurface;
  52. };
  53.  
  54. void GLAPIENTRY
  55. _mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress)
  56. {
  57.    GET_CURRENT_CONTEXT(ctx);
  58.  
  59.    if (!vdpDevice) {
  60.       _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice");
  61.       return;
  62.    }
  63.  
  64.    if (!getProcAddress) {
  65.       _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress");
  66.       return;
  67.    }
  68.  
  69.    if (ctx->vdpDevice || ctx->vdpGetProcAddress || ctx->vdpSurfaces) {
  70.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV");
  71.       return;
  72.    }
  73.  
  74.    ctx->vdpDevice = vdpDevice;
  75.    ctx->vdpGetProcAddress = getProcAddress;
  76.    ctx->vdpSurfaces = _mesa_set_create(NULL, _mesa_hash_pointer,
  77.                                        _mesa_key_pointer_equal);
  78. }
  79.  
  80. static void
  81. unregister_surface(struct set_entry *entry)
  82. {
  83.    struct vdp_surface *surf = (struct vdp_surface *)entry->key;
  84.    GET_CURRENT_CONTEXT(ctx);
  85.    
  86.    if (surf->state == GL_SURFACE_MAPPED_NV) {
  87.       GLintptr surfaces[] = { (GLintptr)surf };
  88.       _mesa_VDPAUUnmapSurfacesNV(1, surfaces);
  89.    }
  90.  
  91.    _mesa_set_remove(ctx->vdpSurfaces, entry);
  92.    free(surf);
  93. }
  94.  
  95. void GLAPIENTRY
  96. _mesa_VDPAUFiniNV(void)
  97. {
  98.    GET_CURRENT_CONTEXT(ctx);
  99.  
  100.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  101.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV");
  102.       return;
  103.    }
  104.  
  105.    _mesa_set_destroy(ctx->vdpSurfaces, unregister_surface);
  106.  
  107.    ctx->vdpDevice = 0;
  108.    ctx->vdpGetProcAddress = 0;
  109.    ctx->vdpSurfaces = NULL;
  110. }
  111.  
  112. static GLintptr
  113. register_surface(struct gl_context *ctx, GLboolean isOutput,
  114.                  const GLvoid *vdpSurface, GLenum target,
  115.                  GLsizei numTextureNames, const GLuint *textureNames)
  116. {
  117.    struct vdp_surface *surf;
  118.    int i;
  119.  
  120.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  121.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV");
  122.       return (GLintptr)NULL;
  123.    }
  124.  
  125.    if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) {
  126.       _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
  127.       return (GLintptr)NULL;
  128.    }
  129.  
  130.    if (target == GL_TEXTURE_RECTANGLE && !ctx->Extensions.NV_texture_rectangle) {
  131.       _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
  132.       return (GLintptr)NULL;
  133.    }
  134.  
  135.    surf = CALLOC_STRUCT( vdp_surface );
  136.    if (surf == NULL) {
  137.       _mesa_error_no_memory("VDPAURegisterSurfaceNV");
  138.       return (GLintptr)NULL;
  139.    }
  140.  
  141.    surf->vdpSurface = vdpSurface;
  142.    surf->target = target;
  143.    surf->access = GL_READ_WRITE;
  144.    surf->state = GL_SURFACE_REGISTERED_NV;
  145.    surf->output = isOutput;
  146.    for (i = 0; i < numTextureNames; ++i) {
  147.       struct gl_texture_object *tex;
  148.       tex  = _mesa_lookup_texture(ctx, textureNames[i]);
  149.       if (tex == NULL) {
  150.          free(surf);
  151.          _mesa_error(ctx, GL_INVALID_OPERATION,
  152.                      "VDPAURegisterSurfaceNV(texture ID not found)");
  153.          return (GLintptr)NULL;
  154.       }
  155.  
  156.       _mesa_lock_texture(ctx, tex);
  157.  
  158.       if (tex->Immutable) {
  159.          _mesa_unlock_texture(ctx, tex);
  160.          free(surf);
  161.          _mesa_error(ctx, GL_INVALID_OPERATION,
  162.                      "VDPAURegisterSurfaceNV(texture is immutable)");
  163.          return (GLintptr)NULL;
  164.       }
  165.  
  166.       if (tex->Target == 0)
  167.          tex->Target = target;
  168.       else if (tex->Target != target) {
  169.          _mesa_unlock_texture(ctx, tex);
  170.          free(surf);
  171.          _mesa_error(ctx, GL_INVALID_OPERATION,
  172.                      "VDPAURegisterSurfaceNV(target mismatch)");
  173.          return (GLintptr)NULL;
  174.       }
  175.  
  176.       /* This will disallow respecifying the storage. */
  177.       tex->Immutable = GL_TRUE;
  178.       _mesa_unlock_texture(ctx, tex);
  179.  
  180.       _mesa_reference_texobj(&surf->textures[i], tex);
  181.    }
  182.  
  183.    _mesa_set_add(ctx->vdpSurfaces, surf);
  184.  
  185.    return (GLintptr)surf;
  186. }
  187.  
  188. GLintptr GLAPIENTRY
  189. _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
  190.                                   GLsizei numTextureNames,
  191.                                   const GLuint *textureNames)
  192. {
  193.    GET_CURRENT_CONTEXT(ctx);
  194.  
  195.    if (numTextureNames != 4) {
  196.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
  197.       return (GLintptr)NULL;
  198.    }
  199.  
  200.    return register_surface(ctx, false, vdpSurface, target,
  201.                            numTextureNames, textureNames);
  202. }
  203.  
  204. GLintptr GLAPIENTRY
  205. _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
  206.                                    GLsizei numTextureNames,
  207.                                    const GLuint *textureNames)
  208. {
  209.    GET_CURRENT_CONTEXT(ctx);
  210.  
  211.    if (numTextureNames != 1) {
  212.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
  213.       return (GLintptr)NULL;
  214.    }
  215.  
  216.    return register_surface(ctx, true, vdpSurface, target,
  217.                            numTextureNames, textureNames);
  218. }
  219.  
  220. GLboolean GLAPIENTRY
  221. _mesa_VDPAUIsSurfaceNV(GLintptr surface)
  222. {
  223.    struct vdp_surface *surf = (struct vdp_surface *)surface;
  224.    GET_CURRENT_CONTEXT(ctx);
  225.  
  226.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  227.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV");
  228.       return false;
  229.    }
  230.  
  231.    if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
  232.       return false;
  233.    }
  234.  
  235.    return true;
  236. }
  237.  
  238. void GLAPIENTRY
  239. _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface)
  240. {
  241.    struct vdp_surface *surf = (struct vdp_surface *)surface;
  242.    struct set_entry *entry;
  243.    int i;
  244.    GET_CURRENT_CONTEXT(ctx);
  245.  
  246.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  247.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnregisterSurfaceNV");
  248.       return;
  249.    }
  250.  
  251.    /* according to the spec it's ok when this is zero */
  252.    if (surface == 0)
  253.       return;
  254.  
  255.    entry = _mesa_set_search(ctx->vdpSurfaces, surf);
  256.    if (!entry) {
  257.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUUnregisterSurfaceNV");
  258.       return;
  259.    }
  260.  
  261.    for (i = 0; i < MAX_TEXTURES; i++) {
  262.       if (surf->textures[i]) {
  263.          surf->textures[i]->Immutable = GL_FALSE;
  264.          _mesa_reference_texobj(&surf->textures[i], NULL);
  265.       }
  266.    }
  267.  
  268.    _mesa_set_remove(ctx->vdpSurfaces, entry);
  269.    free(surf);
  270. }
  271.  
  272. void GLAPIENTRY
  273. _mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
  274.                           GLsizei *length, GLint *values)
  275. {
  276.    struct vdp_surface *surf = (struct vdp_surface *)surface;
  277.    GET_CURRENT_CONTEXT(ctx);
  278.  
  279.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  280.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV");
  281.       return;
  282.    }
  283.  
  284.    if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
  285.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
  286.       return;
  287.    }
  288.  
  289.    if (pname != GL_SURFACE_STATE_NV) {
  290.       _mesa_error(ctx, GL_INVALID_ENUM, "VDPAUGetSurfaceivNV");
  291.       return;
  292.    }
  293.  
  294.    if (bufSize < 1) {
  295.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
  296.       return;
  297.    }
  298.  
  299.    values[0] = surf->state;
  300.  
  301.    if (length != NULL)
  302.       *length = 1;
  303. }
  304.  
  305. void GLAPIENTRY
  306. _mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access)
  307. {
  308.    struct vdp_surface *surf = (struct vdp_surface *)surface;
  309.    GET_CURRENT_CONTEXT(ctx);
  310.  
  311.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  312.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
  313.       return;
  314.    }
  315.  
  316.    if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
  317.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
  318.       return;
  319.    }
  320.  
  321.    if (access != GL_READ_ONLY && access != GL_WRITE_ONLY &&
  322.        access != GL_READ_WRITE) {
  323.  
  324.       _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
  325.       return;
  326.    }
  327.  
  328.    if (surf->state == GL_SURFACE_MAPPED_NV) {
  329.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
  330.       return;
  331.    }
  332.  
  333.    surf->access = access;
  334. }
  335.  
  336. void GLAPIENTRY
  337. _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
  338. {
  339.    GET_CURRENT_CONTEXT(ctx);
  340.    int i;
  341.  
  342.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  343.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
  344.       return;
  345.    }
  346.  
  347.    for (i = 0; i < numSurfaces; ++i) {
  348.       struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
  349.  
  350.       if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
  351.          _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
  352.          return;
  353.       }
  354.  
  355.       if (surf->state == GL_SURFACE_MAPPED_NV) {
  356.          _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
  357.          return;
  358.       }
  359.    }
  360.  
  361.    for (i = 0; i < numSurfaces; ++i) {
  362.       struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
  363.       unsigned numTextureNames = surf->output ? 1 : 4;
  364.       unsigned j;
  365.  
  366.       for (j = 0; j < numTextureNames; ++j) {
  367.          struct gl_texture_object *tex = surf->textures[j];
  368.          struct gl_texture_image *image;
  369.  
  370.          _mesa_lock_texture(ctx, tex);
  371.          image = _mesa_get_tex_image(ctx, tex, surf->target, 0);
  372.          if (!image) {
  373.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV");
  374.             _mesa_unlock_texture(ctx, tex);
  375.             return;
  376.          }
  377.  
  378.          ctx->Driver.FreeTextureImageBuffer(ctx, image);
  379.  
  380.          ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access,
  381.                                      surf->output, tex, image,
  382.                                      surf->vdpSurface, j);
  383.  
  384.          _mesa_unlock_texture(ctx, tex);
  385.       }
  386.       surf->state = GL_SURFACE_MAPPED_NV;
  387.    }
  388. }
  389.  
  390. void GLAPIENTRY
  391. _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
  392. {
  393.    GET_CURRENT_CONTEXT(ctx);
  394.    int i;
  395.  
  396.    if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
  397.       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
  398.       return;
  399.    }
  400.  
  401.    for (i = 0; i < numSurfaces; ++i) {
  402.       struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
  403.  
  404.       if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
  405.          _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
  406.          return;
  407.       }
  408.  
  409.       if (surf->state != GL_SURFACE_MAPPED_NV) {
  410.          _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
  411.          return;
  412.       }
  413.    }
  414.  
  415.    for (i = 0; i < numSurfaces; ++i) {
  416.       struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
  417.       unsigned numTextureNames = surf->output ? 1 : 4;
  418.       unsigned j;
  419.  
  420.       for (j = 0; j < numTextureNames; ++j) {
  421.          struct gl_texture_object *tex = surf->textures[j];
  422.          struct gl_texture_image *image;
  423.  
  424.          _mesa_lock_texture(ctx, tex);
  425.  
  426.          image = _mesa_select_tex_image(tex, surf->target, 0);
  427.  
  428.          ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access,
  429.                                        surf->output, tex, image,
  430.                                        surf->vdpSurface, j);
  431.  
  432.          if (image)
  433.             ctx->Driver.FreeTextureImageBuffer(ctx, image);
  434.  
  435.          _mesa_unlock_texture(ctx, tex);
  436.       }
  437.       surf->state = GL_SURFACE_REGISTERED_NV;
  438.    }
  439. }
  440.