vdpau-driver-0.7.4/000077500000000000000000000000001203356434100141335ustar00rootroot00000000000000vdpau-driver-0.7.4/.gitignore000066400000000000000000000005351203356434100161260ustar00rootroot00000000000000*~ *.o *.lo *.la *.orig *.rej *.loT *.bin *.pc .deps .libs install-sh libtool ltmain.sh compile missing Makefile Makefile.in config.h config.h.in stamp-h1 aclocal.m4 autom4te.cache config.guess config.log config.status config.sub configure depcomp TAGS /debian.upstream/changelog /debian.upstream/control /debian.upstream/libva-vdpau-driver.install vdpau-driver-0.7.4/AUTHORS000066400000000000000000000001071203356434100152010ustar00rootroot00000000000000Gwenole Beauchesne - Primary author vdpau-driver-0.7.4/COPYING000066400000000000000000000431031203356434100151670ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. vdpau-driver-0.7.4/Makefile.am000066400000000000000000000011561203356434100161720ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign SUBDIRS = debian.upstream src # Extra clean files so that maintainer-clean removes *everything* MAINTAINERCLEANFILES = \ aclocal.m4 compile config.guess config.sub \ configure depcomp install-sh ltmain.sh \ Makefile.in missing $(DEBIANGENFILES) DEB_BUILDDIR = debian.build deb: @[ -d debian ] || ln -s debian.upstream debian dpkg-buildpackage -rfakeroot -uc -us deb.upstream: dist -mkdir -p $(DEB_BUILDDIR) cd $(DEB_BUILDDIR) && \ rm -rf $(PACKAGE)-$(VERSION) && \ tar zxvf ../$(PACKAGE)-$(VERSION).tar.gz && \ cd $(PACKAGE)-$(VERSION) && \ $(MAKE) deb -f Makefile.am vdpau-driver-0.7.4/NEWS000066400000000000000000000136641203356434100146440ustar00rootroot00000000000000libva-vdpau-driver NEWS -- summary of changes. 2012-10-05 Copyright (C) 2009-2011 Splitted-Desktop Systems Version 0.7.4 - 05.Oct.2012 * Use upstream libva version * Avoid X11 socket leak (Marco De Michele) * Fix MPEG-2 decoding from gstreamer-vaapi * Fix compatibility glue for vaBufferInfo() * Fix subpicture blend state (Holger Kaelberer) * Fix multithreaded issues (Philip Lorenz, Krzysztof Kotlenga) * Add support for global-alpha subpictures (Holger Kaelberer) Version 0.7.3 - 26.Feb.2011 * Add compatibility glue with libva >= 1.0.8 * Fix possible crash when rendering multiple surfaces at once * Fix build if no OpenGL header is available (libva >= 0.31.1) * Fix VA/GLX build with upstream libva and newer OpenGL headers Version 0.7.2 - 08.Oct.2010 * Drop explicit link against libva * Fix detection of the NVIDIA driver version * Add debug info through VDPAU_VIDEO_DEBUG= * Add compatibility glue with original VA-API 0.31.x * Allow high-quality scaling through vaPutSurface() (VA_FILTER_SCALING_HQ) Version 0.7.1 - 05.Oct.2010 * Fix X11 display locking issues * Add support for GL_TEXTURE_RECTANGLE_ARB textures * Allow SMPTE-240M colorspace conversion (VA_SRC_SMPTE_240) Version 0.7.0 - 09.Aug.2010 * Add support for VA-API 0.31.1-sds1 * Use GL_NV_vdpau_interop extension for VA/GLX * Optimize rendering of multiple surfaces per window Version 0.6.9 - 17.Apr.2010 * Fix deinterlacing * Fix VA context destruction * Fix vaCreateConfig() to validate profile * Fix output surface creation code to detect errors Version 0.6.8 - 13.Apr.2010 * Drop superfluous asserts * Fix OpenGL rendering for XBMC * Fix rendering when the window size changed * Fix MPEG-4 decoding of video clips with B-frames Version 0.6.7 - 04.Apr.2010 * Fix build without GLX support * Fix VA/GLX to preserve caller's GL context * Fix vaCopySurfaceGLX() to handle GL_RGBA8 textures Version 0.6.6 - 18.Mar.2010 * Add I420 image format * Allocate image data on 16-byte boundaries * Fix vaCreateImage() to cleanup data on error * Fix vaTerminate() to destroy the VDPAU device * Add support for VA-API 0.31.0-sds6 Version 0.6.5 - 08.Mar.2010 * Fix display queue initialization * Fix internal functions linkage. i.e. don't export internals * Fix another VOP header reconstruction bug for MPEG-4 decoding Version 0.6.4 - 01.Mar.2010 * Fix rendering of multiple surfaces per window * Fix rendering of multiple subpictures per surface * Add support for VA-API 0.31.0-sds5 * Add support for VA_CLEAR_DRAWABLE to vaPutSurface() Version 0.6.3 - 27.Jan.2010 * Fix video mixer caching * Fix rendering of subpictures * Add background-color display attribute Version 0.6.2 - 19.Jan.2010 * Fix vaGetImage() with YV12 format * Fix window resize by less than 256 pixels in either dimension * Allow vaPutSurface() to render to multiple drawables from a single surface Version 0.6.1 - 21.Dec.2009 * Set VDPAU_VIDEO_DPB to 0, i.e. use H.264 DPB from libVA * Fix VOP header reconstruction bug for MPEG-4 decoding * Fix build with older VDPAU headers (without MPEG-4 support) * Fix image palette allocation and conversion to VDPAU format Version 0.6.0 - 27.Nov.2009 * Add MPEG-4 decoding support * Add support for bob deinterlacing * Add brightness/contrast/hue/saturation display attributes * Allow ITU-R BT.601/709 colorspace conversion flags to vaPutSurface() Version 0.5.2 - 15.Oct.2009 * Add indexed color subpicture formats * Fix and optimize rendering of subpictures * Fix vaCreateImage() to allow RGBA subpictures * Allocate VdpOutputSurface on-demand in vaGetImage() for RGBA formats * Make it possible to vaPutSurface() a surface not bound to any VA context Version 0.5.1 - 12.Oct.2009 * Use VA_INVALID_ID for invalid contextes * Fix RGB image formats to have a unique FOURCC * Fix vaCreateImage() when output VAImage points to stack * Fix vaPutSurface() to fail gracefully if the Drawable is not ready Version 0.5.0 - 06.Oct.2009 * Add support for subpictures * Add vaPutImage() though VDPAU has limited API * Handle vaGetImage() with partial region in RGBA format Version 0.4.2 - 28.Sep.2009 * Fix vaPutSurface() display bounds * Fix vaGetImage() with YV12 pixels Version 0.4.1 - 10.Sep.2009 * Add VADisplayAttributes * Add support for VA-API 0.31 * Add support for OpenGL extensions to VA-API (v3) * Fix vaQueryConfigEntrypoints() to first check the profile is supported Version 0.4.0 - 27.Aug.2009 * Add support for OpenGL extensions to VA-API * Fix VAImageID pool memory leak in vaTerminate() Version 0.3.3 - 25.Aug.2009 * Fix H.264 DPB synchronization * Fix vaGetImage() with YV12 format * Add support for vaSyncSurface() and vaQuerySurfaceStatus() Version 0.3.2 - 25.Jun.2009 * Add support for VA-API 0.30 Version 0.3.1 - 23.Apr.2009 * Add RGBA image formats, including for vaGetImage(). Version 0.3.0 - 16.Apr.2009 * Don't expose RGBA formats in vaQueryImageFormats() * Add support for VAImage related functions: - vaCreateImage(), vaDestroyImage() - vaGetImage() for full surface readback only (i.e. no partial reads) Version 0.2.6 - 20.Mar.2009 * Handle VC-1 skipped P-frames Version 0.2.5 - 18.Mar.2009 * Handle multiple VASliceDataBuffers * Handle H.264 bitstreams without start_code_prefix_one_3byte * Fix destruction of output surfaces * Fix VC-1 picture info fields (pquant and deblockEnable) Version 0.2.4 - 03.Mar.2009 * Upgrade to VA-API 0.29.0-sds7 extensions * Fix corruption decoding field-coded pictures in MBAFF H.264 clips Version 0.2.3 - 25.Feb.2009 * Add vaQueryImageFormats() * Sync with VDPAU additions from NVIDIA drivers 180.35 * Allow tracing of control structures through VDPAU_VIDEO_TRACE=1 * Fix decoding of some full HD bitstreams with many reference frames Version 0.2.2 - 05.Feb.2009 * Fix VC-1 decoding of bitstreams with B-frames * Fix VdpPictureInfoH264::is_reference (use reference_pic_flag) Version 0.2.1 - 28.Jan.2009 * Fix VC-1 decoding * Add debian packaging rules Version 0.2.0 - 23.Jan.2009 * Add support for VC-1 * Relax size requirements in vaPutSurface() Version 0.1.0 - 16.Jan.2009 * Initial public release vdpau-driver-0.7.4/README000066400000000000000000000012351203356434100150140ustar00rootroot00000000000000 libva-vdpau-driver A VDPAU-based backend for VA-API Copyright (C) 2009-2011 Splitted-Desktop Systems License ------- libva-vdpau-driver is available under the terms of the GNU General Public License. Overview -------- libva-vdpau-driver consists in a VDPAU-based backend for VA-API. Requirements ------------ libVA API version (not package) GLX support MPEG-4 support 0.29-branch >= 0.29.0-sds8 No No 0.30-branch >= 0.30.0-sds1 No No 0.30-branch >= 0.30.4-sds5 Yes No upstream 0.31-branch No No 0.31-branch >= 0.31.0-sds1 Yes No 0.31-branch >= 0.31.0-sds4 Yes Yes mplayer-vaapi >= 20090320 patchset is also needed if you intend to use MPlayer. vdpau-driver-0.7.4/autogen.sh000077500000000000000000000000641203356434100161340ustar00rootroot00000000000000#! /bin/sh autoreconf -v --install ./configure "$@" vdpau-driver-0.7.4/configure.ac000066400000000000000000000162141203356434100164250ustar00rootroot00000000000000# vdpau_video package version number m4_define([vdpau_video_major_version], [0]) m4_define([vdpau_video_minor_version], [7]) m4_define([vdpau_video_micro_version], [4]) m4_define([vdpau_video_pre_version], [0]) m4_define([vdpau_video_version], [vdpau_video_major_version.vdpau_video_minor_version.vdpau_video_micro_version]) m4_if(vdpau_video_pre_version, [0], [], [ m4_append([vdpau_video_version], vdpau_video_pre_version, [.pre]) ]) # VA-API minimum version number m4_define([va_api_x11_version], [0.31.0]) m4_define([va_api_glx_version], [0.32.0]) # libva package version number m4_define([libva_package_x11_version], [1.0.3]) m4_define([libva_package_glx_version], [1.0.9]) AC_PREREQ([2.57]) AC_INIT([vdpau_video], [vdpau_video_version], [gwenole.beauchesne@intel.com], [libva-vdpau-driver]) AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE AM_CONFIG_HEADER([src/config.h]) VDPAU_VIDEO_MAJOR_VERSION=vdpau_video_major_version VDPAU_VIDEO_MINOR_VERSION=vdpau_video_minor_version VDPAU_VIDEO_MICRO_VERSION=vdpau_video_micro_version AC_DEFINE([VDPAU_VIDEO_MAJOR_VERSION], [vdpau_video_major_version], [Major version of the driver]) AC_DEFINE([VDPAU_VIDEO_MINOR_VERSION], [vdpau_video_minor_version], [Minor version of the driver]) AC_DEFINE([VDPAU_VIDEO_MICRO_VERSION], [vdpau_video_micro_version], [Micro version of the driver]) AC_DEFINE([VDPAU_VIDEO_PRE_VERSION], [vdpau_video_pre_version], [Preversion of the driver]) VDPAU_VIDEO_LT_LDFLAGS="-avoid-version" AC_SUBST(VDPAU_VIDEO_LT_LDFLAGS) AC_DEFUN([AC_DEFINE_01], [ if test "$2" = "yes" -o "$2" = "guessing yes"; then AC_DEFINE($1, 1, $3) else AC_DEFINE($1, 0, $3) fi ]) AC_ARG_ENABLE(glx, AC_HELP_STRING([--enable-glx], [enable OpenGL/X11 @<:@default=yes@:>@]), [], [enable_glx="yes"]) AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable debugging information]), [], [enable_debug="yes"]) AC_DEFINE_01(USE_DEBUG, "$enable_debug", [Enable debugging information]) AC_ARG_ENABLE(tracer, AC_HELP_STRING([--enable-tracer], [enable VDPAU tracer]), [], [enable_tracer="yes"]) AC_DEFINE_01(USE_TRACER, "$enable_tracer", [Enable VDPAU tracer]) AC_DISABLE_STATIC AC_PROG_LIBTOOL AC_PROG_CC AC_C_BIGENDIAN AC_HEADER_STDC AC_SYS_LARGEFILE dnl Use pretty build output with automake >= 1.11 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [ AM_DEFAULT_VERBOSITY=1 AC_SUBST(AM_DEFAULT_VERBOSITY) ]) dnl We want pthreads. Try libpthread first, then libc_r (FreeBSD), then PTL. HAVE_PTHREADS=yes AC_CHECK_LIB(pthread, pthread_create, , [ AC_CHECK_LIB(c_r, pthread_create, , [ AC_CHECK_LIB(PTL, pthread_create, , [ HAVE_PTHREADS=no ]) ]) ]) if test "x$HAVE_PTHREADS" = "xyes"; then AC_DEFINE(HAVE_PTHREADS, 1, [Defined if pthreads are available]) fi dnl Checks for libraries. AC_CHECK_LIB(m, tan) AC_CHECK_LIB(rt, timer_create) dnl Checks for library functions. AC_CHECK_FUNCS(clock_gettime) dnl Check for __attribute__((visibility())) AC_CACHE_CHECK([whether __attribute__((visibility())) is supported], vdpau_cv_visibility_attribute, [cat > conftest.c </dev/null 2>&1; then if grep '\.hidden.*foo' conftest.s >/dev/null; then if grep '\.protected.*bar' conftest.s >/dev/null; then vdpau_cv_visibility_attribute=yes fi fi fi rm -f conftest.[cs] ]) if test $vdpau_cv_visibility_attribute = yes; then AC_DEFINE([HAVE_VISIBILITY_ATTRIBUTE], 1, [Define to use the __attribute__((visibility())) extension]) fi dnl Check for OpenGL USE_GLX=1 if test "$enable_glx" != "yes"; then USE_GLX=0 fi GL_DEPS_CFLAGS="" GL_DEPS_LIBS="" AC_CHECK_HEADERS([GL/gl.h GL/glext.h GL/glx.h], [], [USE_GLX=0], [ #ifdef HAVE_GL_GL_H # include #endif ]) AC_CHECK_LIB(GL, glXCreateContext, [GL_DEPS_LIBS="-lGL -ldl"], [USE_GLX=0]) AC_SUBST(GL_DEPS_CFLAGS) AC_SUBST(GL_DEPS_LIBS) dnl Check for VA-API PKG_CHECK_MODULES(LIBVA_DEPS, [libva]) PKG_CHECK_MODULES(LIBVA_X11_DEPS, [libva-x11 >= va_api_x11_version], [LIBVA_PACKAGE_VERSION=libva_package_x11_version]) PKG_CHECK_MODULES(LIBVA_GLX_DEPS, [libva-glx >= va_api_glx_version], [LIBVA_PACKAGE_VERSION=libva_package_glx_version], [USE_GLX=0]) VA_VERSION=`$PKG_CONFIG --modversion libva` VA_MAJOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f1` VA_MINOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f2` VA_MICRO_VERSION=`echo "$VA_VERSION" | cut -d'.' -f3` VA_VERSION_STR="$VA_VERSION" va_full_version_int=`expr ${VA_MAJOR_VERSION:-0} "*" 1000000 + \ ${VA_MINOR_VERSION:-0} "*" 10000 + \ ${VA_MICRO_VERSION:-0} "*" 100 + \ 0` VA_DRIVER_INIT_FUNC="__vaDriverInit_${VA_MAJOR_VERSION}_${VA_MINOR_VERSION}" AC_DEFINE_UNQUOTED([VA_DRIVER_INIT_FUNC], [$VA_DRIVER_INIT_FUNC], [Define driver entry-point]) dnl Check for VA-API drivers path AC_MSG_CHECKING([for VA drivers path]) LIBVA_DRIVERS_PATH=`$PKG_CONFIG libva --variable driverdir` if test -z "$LIBVA_DRIVERS_PATH"; then LIBVA_DRIVERS_PATH="/usr/lib/xorg/modules/drivers" fi AC_MSG_RESULT([$LIBVA_DRIVERS_PATH]) AC_SUBST(LIBVA_DRIVERS_PATH) dnl Check for VDPAU AC_CACHE_CHECK([for VDPAU], ac_cv_have_vdpau, [ saved_LIBS="$LIBS" LIBS="$LIBS -lvdpau" AC_TRY_LINK( [#include ], [vdp_device_create_x11(0,0,0,0)], [ac_cv_have_vdpau="yes" HAVE_VDPAU=1], [ac_cv_have_vdpau="no" HAVE_VDPAU=0]) ]) if test "$ac_cv_have_vdpau" = "no"; then AC_MSG_ERROR([you need VDPAU to build this package]) fi AC_CACHE_CHECK([for VDPAU/MPEG-4 support], ac_cv_have_vdpau_mpeg4, [ AC_TRY_LINK( [#include ], [VdpPictureInfoMPEG4Part2 pic_info], [ac_cv_have_vdpau_mpeg4="yes" HAVE_VDPAU_MPEG4=1], [ac_cv_have_vdpau_mpeg4="no" HAVE_VDPAU_MPEG4=0]) ]) AC_DEFINE_UNQUOTED(HAVE_VDPAU_MPEG4, [$HAVE_VDPAU_MPEG4], [VDPAU/MPEG-4 support]) dnl Check for VDPAU version (poor man's check, no pkgconfig joy) VDPAU_VERSION=`cat << EOF | $CC -E - | grep ^vdpau_version | cut -d' ' -f2 #include vdpau_version VDPAU_VERSION EOF ` AC_DEFINE_UNQUOTED(USE_GLX, $USE_GLX, [Defined to 1 if GLX is enabled]) AM_CONDITIONAL(USE_GLX, test $USE_GLX -eq 1) VDPAU_VIDEO_CFLAGS="$LIBVA_DEPS_CFLAGS" VDPAU_VIDEO_LIBS="" if test $USE_GLX -eq 1; then VDPAU_VIDEO_CFLAGS="$VDPAU_VIDEO_CFLAGS $GL_DEPS_CFLAGS" VDPAU_VIDEO_LIBS="$VDPAU_VIDEO_LIBS $GL_DEPS_LIBS" fi AC_SUBST(VDPAU_VIDEO_CFLAGS) AC_SUBST(VDPAU_VIDEO_LIBS) AC_SUBST(LIBVA_PACKAGE_VERSION) AC_OUTPUT([ Makefile debian.upstream/Makefile src/Makefile ]) dnl Print summary echo echo $PACKAGE configuration summary: echo echo VA-API version ................... : $VA_VERSION_STR echo VA-API drivers path .............. : $LIBVA_DRIVERS_PATH echo VDPAU version .................... : $VDPAU_VERSION echo VDPAU/MPEG-4 support ............. : $(test $HAVE_VDPAU_MPEG4 -eq 1 && echo yes || echo no) echo GLX support ...................... : $(test $USE_GLX -eq 1 && echo yes || echo no) echo vdpau-driver-0.7.4/debian.upstream/000077500000000000000000000000001203356434100172145ustar00rootroot00000000000000vdpau-driver-0.7.4/debian.upstream/Makefile.am000066400000000000000000000012751203356434100212550ustar00rootroot00000000000000DEBIANFILES = \ changelog.in \ compat \ control.in \ copyright \ libva-vdpau-driver.install.in \ rules \ $(NULL) DEBIANGENFILES = \ changelog \ control \ libva-vdpau-driver.install \ $(NULL) EXTRA_DIST = $(DEBIANFILES) dist_noinst_DATA = $(DEBIANGENFILES) # Extra clean files so that maintainer-clean removes *everything* MAINTAINERCLEANFILES = Makefile.in $(DEBIANGENFILES) $(DEBIANGENFILES): %: %.in Makefile -sed \ -e 's|\@PACKAGE_VERSION\@|$(PACKAGE_VERSION)|' \ -e 's|\@LIBVA_PACKAGE_VERSION\@|$(LIBVA_PACKAGE_VERSION)|' \ -e 's|\@LIBVA_DRIVERS_PATH\@|$(LIBVA_DRIVERS_PATH)|' \ -e 's|\@DATE\@|'"`LC_ALL=C date +'%a, %d %b %Y %X %z'`"'|' \ $< > $@ vdpau-driver-0.7.4/debian.upstream/changelog.in000066400000000000000000000002731203356434100214750ustar00rootroot00000000000000libva-vdpau-driver (@PACKAGE_VERSION@-1) unstable; urgency=low * Autogenerated package, see NEWS file for ChangeLog. -- Gwenole Beauchesne @DATE@ vdpau-driver-0.7.4/debian.upstream/compat000066400000000000000000000000021203356434100204120ustar00rootroot000000000000005 vdpau-driver-0.7.4/debian.upstream/control.in000066400000000000000000000014011203356434100212200ustar00rootroot00000000000000Source: libva-vdpau-driver Section: libs Priority: optional Maintainer: Gwenole Beauchesne Build-Depends: debhelper (>= 5), cdbs, libva-dev (>= @LIBVA_PACKAGE_VERSION@) Standards-Version: 3.7.2 Package: libva-vdpau-driver Section: libs Architecture: any Depends: libva1 (>= @LIBVA_PACKAGE_VERSION@), ${shlibs:Depends}, ${misc:Depends} Description: VDPAU-based backend for VA-API Video decode driver for NVIDIA chipsets (VDPAU implementation). Package: libva-vdpau-driver-dbg Section: libdevel Architecture: any Depends: libva-vdpau-driver (= ${Source-Version}) Description: VDPAU-based backend for VA-API Video decode driver for NVIDIA chipsets (VDPAU implementation). . This package contains the debug files. vdpau-driver-0.7.4/debian.upstream/copyright000066400000000000000000000017451203356434100211560ustar00rootroot00000000000000This package is maintained by: Gwenole Beauchesne License: Copyright (C) 2009-2011 Splitted-Desktop Systems This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. On Debian GNU/Linux systems, the complete text of the GNU General Public License is in `/usr/share/common-licenses/GPL'. vdpau-driver-0.7.4/debian.upstream/libva-vdpau-driver.install.in000066400000000000000000000000441203356434100247120ustar00rootroot00000000000000debian/tmp@LIBVA_DRIVERS_PATH@/*.so vdpau-driver-0.7.4/debian.upstream/rules000077500000000000000000000006611203356434100202770ustar00rootroot00000000000000#!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/autotools.mk include /usr/share/cdbs/1/rules/simple-patchsys.mk include /usr/share/cdbs/1/rules/utils.mk # Allow SMP build ifeq ($(DEBIAN_BUILD_NCPUS),) DEBIAN_BUILD_NCPUS = $(shell /usr/bin/getconf _NPROCESSORS_ONLN) endif ifneq ($(DEBIAN_BUILD_NCPUS),) EXTRA_MAKE_FLAGS += -j$(DEBIAN_BUILD_NCPUS) endif MAKE += $(EXTRA_MAKE_FLAGS) vdpau-driver-0.7.4/src/000077500000000000000000000000001203356434100147225ustar00rootroot00000000000000vdpau-driver-0.7.4/src/Makefile.am000066400000000000000000000032661203356434100167650ustar00rootroot00000000000000DRIVERS = nvidia DRIVERS += s3g # native VA-API driver is too old, so use VDPAU based one INCLUDES = \ $(VDPAU_VIDEO_CFLAGS) LDADD = \ $(VDPAU_VIDEO_LT_LDFLAGS) -module \ -no-undefined -module -Wl,--no-undefined if USE_GLX source_glx_h = vdpau_video_glx.h utils_glx.h source_glx_c = vdpau_video_glx.c utils_glx.c endif source_x11_h = vdpau_video_x11.h utils_x11.h source_x11_c = vdpau_video_x11.c utils_x11.c source_h = \ debug.h \ object_heap.h \ sysdeps.h \ uasyncqueue.h \ ulist.h \ uqueue.h \ utils.h \ vaapi_compat.h \ vdpau_buffer.h \ vdpau_decode.h \ vdpau_driver.h \ vdpau_driver_template.h \ vdpau_dump.h \ vdpau_gate.h \ vdpau_image.h \ vdpau_mixer.h \ vdpau_subpic.h \ vdpau_video.h \ $(source_glx_h) \ $(source_x11_h) source_c = \ debug.c \ object_heap.c \ put_bits.h \ uasyncqueue.c \ ulist.c \ uqueue.c \ utils.c \ vdpau_buffer.c \ vdpau_decode.c \ vdpau_driver.c \ vdpau_dump.c \ vdpau_gate.c \ vdpau_image.c \ vdpau_mixer.c \ vdpau_subpic.c \ vdpau_video.c \ $(source_glx_c) \ $(source_x11_c) vdpau_drv_video_la_LTLIBRARIES = vdpau_drv_video.la vdpau_drv_video_ladir = @LIBVA_DRIVERS_PATH@ vdpau_drv_video_la_SOURCES = $(source_c) vdpau_drv_video_la_LIBADD = $(VDPAU_VIDEO_LIBS) -lX11 vdpau_drv_video_la_LDFLAGS = $(LDADD) noinst_HEADERS = $(source_h) EXTRA_DIST = \ $(source_glx_c) \ $(source_glx_h) \ $(source_x11_c) \ $(source_x11_h) install-data-hook: cd $(DESTDIR)$(LIBVA_DRIVERS_PATH) ; \ for drv in $(DRIVERS); do \ ln -s vdpau_drv_video.so $${drv}_drv_video.so; \ done # Extra clean files so that maintainer-clean removes *everything* MAINTAINERCLEANFILES = Makefile.in config.h.in vdpau-driver-0.7.4/src/debug.c000066400000000000000000000064431203356434100161630ustar00rootroot00000000000000/* * debug.c - Debugging utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "debug.h" #include "utils.h" #include static void do_vfprintf(FILE *fp, const char *msg, va_list args) { /* XXX: use another printf() function, e.g. a valgrind one to maintain correct control flow */ vfprintf(fp, msg, args); } static void do_fprintf(FILE *fp, const char *msg, ...) { va_list args; va_start(args, msg); do_vfprintf(fp, msg, args); va_end(args); } void vdpau_error_message(const char *msg, ...) { va_list args; do_fprintf(stderr, "%s: error: ", PACKAGE_NAME); va_start(args, msg); do_vfprintf(stderr, msg, args); va_end(args); } void vdpau_information_message(const char *msg, ...) { va_list args; do_fprintf(stdout, "%s: ", PACKAGE_NAME); va_start(args, msg); do_vfprintf(stdout, msg, args); va_end(args); } static int debug_enabled(void) { static int g_debug_enabled = -1; if (g_debug_enabled < 0) { if (getenv_yesno("VDPAU_VIDEO_DEBUG", &g_debug_enabled) < 0) g_debug_enabled = 0; } return g_debug_enabled; } void debug_message(const char *msg, ...) { va_list args; if (!debug_enabled()) return; do_fprintf(stdout, "%s: ", PACKAGE_NAME); va_start(args, msg); do_vfprintf(stdout, msg, args); va_end(args); } static int g_trace_is_new_line = 1; static int g_trace_indent = 0; int trace_enabled(void) { static int g_trace_enabled = -1; if (g_trace_enabled < 0) { if (getenv_yesno("VDPAU_VIDEO_TRACE", &g_trace_enabled) < 0) g_trace_enabled = 0; } return g_trace_enabled; } static int trace_indent_width(void) { static int g_indent_width = -1; if (g_indent_width < 0) { if (getenv_int("VDPAU_VIDEO_TRACE_INDENT_WIDTH", &g_indent_width) < 0) g_indent_width = 4; } return g_indent_width; } void trace_indent(int inc) { g_trace_indent += inc; } void trace_print(const char *format, ...) { va_list args; if (g_trace_is_new_line) { int i, j, n; printf("%s: ", PACKAGE_NAME); n = trace_indent_width(); for (i = 0; i < g_trace_indent; i++) { for (j = 0; j < n / 4; j++) printf(" "); for (j = 0; j < n % 4; j++) printf(" "); } } va_start(args, format); vfprintf(stdout, format, args); va_end(args); g_trace_is_new_line = (strchr(format, '\n') != NULL); if (g_trace_is_new_line) fflush(stdout); } vdpau-driver-0.7.4/src/debug.h000066400000000000000000000027201203356434100161620ustar00rootroot00000000000000/* * debug.h - Debugging utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef DEBUG_H #define DEBUG_H void vdpau_error_message(const char *msg, ...) attribute_hidden; void vdpau_information_message(const char *msg, ...) attribute_hidden; void debug_message(const char *msg, ...) attribute_hidden; #if DEBUG && USE_DEBUG # define D(x) x # define bug debug_message #else # define D(x) #endif // Returns TRUE if debug trace is enabled int trace_enabled(void) attribute_hidden; // Increase or decrease indentation level void trace_indent(int inc) attribute_hidden; // Print message on the debug trace output void trace_print(const char *format, ...) attribute_hidden; #endif /* DEBUG_H */ vdpau-driver-0.7.4/src/object_heap.c000066400000000000000000000200211203356434100173240ustar00rootroot00000000000000/* * object_heap.c - Management of VA-API resources * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include #include "object_heap.h" /* This code is: * Copyright (c) 2007 Intel Corporation. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define LAST_FREE -1 #define ALLOCATED -2 /* * Expands the heap * Return 0 on success, -1 on error */ static int object_heap_expand(object_heap_p heap) { int i; void *new_heap_index; int next_free; int new_heap_size = heap->heap_size + heap->heap_increment; int bucket_index = new_heap_size / heap->heap_increment - 1; if (bucket_index >= heap->num_buckets) { int new_num_buckets = heap->num_buckets + 8; void **new_bucket; new_bucket = realloc(heap->bucket, new_num_buckets * sizeof(void *)); if (NULL == new_bucket) { return -1; } heap->num_buckets = new_num_buckets; heap->bucket = new_bucket; } new_heap_index = (void *) malloc(heap->heap_increment * heap->object_size); if (NULL == new_heap_index) { return -1; /* Out of memory */ } heap->bucket[bucket_index] = new_heap_index; next_free = heap->next_free; for (i = new_heap_size; i-- > heap->heap_size;) { object_base_p obj = (object_base_p)(new_heap_index + (i - heap->heap_size) * heap->object_size); obj->id = i + heap->id_offset; obj->next_free = next_free; next_free = i; } heap->next_free = next_free; heap->heap_size = new_heap_size; return 0; /* Success */ } /* * Return 0 on success, -1 on error */ int object_heap_init(object_heap_p heap, int object_size, int id_offset) { pthread_mutex_init(&heap->mutex, NULL); heap->object_size = object_size; heap->id_offset = id_offset & OBJECT_HEAP_OFFSET_MASK; heap->heap_size = 0; heap->heap_increment = 16; heap->next_free = LAST_FREE; heap->num_buckets = 0; heap->bucket = NULL; return object_heap_expand(heap); } /* * Allocates an object * Returns the object ID on success, returns -1 on error */ static int object_heap_allocate_unlocked(object_heap_p heap) { object_base_p obj; int bucket_index, obj_index; if (LAST_FREE == heap->next_free) { if (-1 == object_heap_expand(heap)) { return -1; /* Out of memory */ } } ASSERT(heap->next_free >= 0); bucket_index = heap->next_free / heap->heap_increment; obj_index = heap->next_free % heap->heap_increment; obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size); heap->next_free = obj->next_free; obj->next_free = ALLOCATED; return obj->id; } int object_heap_allocate(object_heap_p heap) { int ret; pthread_mutex_lock(&heap->mutex); ret = object_heap_allocate_unlocked(heap); pthread_mutex_unlock(&heap->mutex); return ret; } /* * Lookup an object by object ID * Returns a pointer to the object on success, returns NULL on error */ static object_base_p object_heap_lookup_unlocked(object_heap_p heap, int id) { object_base_p obj; int bucket_index, obj_index; if ((id < heap->id_offset) || (id > (heap->heap_size + heap->id_offset))) { return NULL; } id &= OBJECT_HEAP_ID_MASK; bucket_index = id / heap->heap_increment; obj_index = id % heap->heap_increment; obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size); /* Check if the object has in fact been allocated */ if (obj->next_free != ALLOCATED) { return NULL; } return obj; } object_base_p object_heap_lookup(object_heap_p heap, int id) { object_base_p obj; pthread_mutex_lock(&heap->mutex); obj = object_heap_lookup_unlocked(heap, id); pthread_mutex_unlock(&heap->mutex); return obj; } /* * Iterate over all objects in the heap. * Returns a pointer to the first object on the heap, returns NULL if heap is empty. */ object_base_p object_heap_first(object_heap_p heap, object_heap_iterator *iter) { *iter = -1; return object_heap_next(heap, iter); } /* * Iterate over all objects in the heap. * Returns a pointer to the next object on the heap, returns NULL if heap is empty. */ static object_base_p object_heap_next_unlocked(object_heap_p heap, object_heap_iterator *iter) { object_base_p obj; int bucket_index, obj_index; int i = *iter + 1; while (i < heap->heap_size) { bucket_index = i / heap->heap_increment; obj_index = i % heap->heap_increment; obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size); if (obj->next_free == ALLOCATED) { *iter = i; return obj; } i++; } *iter = i; return NULL; } object_base_p object_heap_next(object_heap_p heap, object_heap_iterator *iter) { object_base_p obj; pthread_mutex_lock(&heap->mutex); obj = object_heap_next_unlocked(heap, iter); pthread_mutex_unlock(&heap->mutex); return obj; } /* * Frees an object */ static void object_heap_free_unlocked(object_heap_p heap, object_base_p obj) { /* Check if the object has in fact been allocated */ ASSERT(obj->next_free == ALLOCATED); obj->next_free = heap->next_free; heap->next_free = obj->id & OBJECT_HEAP_ID_MASK; } void object_heap_free(object_heap_p heap, object_base_p obj) { if (!obj) return; pthread_mutex_lock(&heap->mutex); object_heap_free_unlocked(heap, obj); pthread_mutex_unlock(&heap->mutex); } /* * Destroys a heap, the heap must be empty. */ void object_heap_destroy(object_heap_p heap) { object_base_p obj; int bucket_index, obj_index, i; /* Check if heap is empty */ for (i = 0; i < heap->heap_size; i++) { /* Check if object is not still allocated */ bucket_index = i / heap->heap_increment; obj_index = i % heap->heap_increment; obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size); ASSERT(obj->next_free != ALLOCATED); } for (i = 0; i < heap->heap_size / heap->heap_increment; i++) { free(heap->bucket[i]); } pthread_mutex_destroy(&heap->mutex); free(heap->bucket); heap->bucket = NULL; heap->heap_size = 0; heap->next_free = LAST_FREE; } vdpau-driver-0.7.4/src/object_heap.h000066400000000000000000000050401203356434100173350ustar00rootroot00000000000000/* * object_heap.h - Management of VA-API resources * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VA_OBJECT_HEAP_H #define VA_OBJECT_HEAP_H #define OBJECT_HEAP_OFFSET_MASK 0x7f000000 #define OBJECT_HEAP_ID_MASK 0x00ffffff typedef struct object_base *object_base_p; typedef struct object_heap *object_heap_p; struct object_base { int id; int next_free; }; struct object_heap { pthread_mutex_t mutex; int object_size; int id_offset; int next_free; int heap_size; int heap_increment; void **bucket; int num_buckets; }; typedef int object_heap_iterator; /* * Return 0 on success, -1 on error */ int object_heap_init(object_heap_p heap, int object_size, int id_offset) attribute_hidden; /* * Allocates an object * Returns the object ID on success, returns -1 on error */ int object_heap_allocate(object_heap_p heap) attribute_hidden; /* * Lookup an allocated object by object ID * Returns a pointer to the object on success, returns NULL on error */ object_base_p object_heap_lookup(object_heap_p heap, int id) attribute_hidden; /* * Iterate over all objects in the heap. * Returns a pointer to the first object on the heap, returns NULL if heap is empty. */ object_base_p object_heap_first(object_heap_p heap, object_heap_iterator *iter) attribute_hidden; /* * Iterate over all objects in the heap. * Returns a pointer to the next object on the heap, returns NULL if heap is empty. */ object_base_p object_heap_next(object_heap_p heap, object_heap_iterator *iter) attribute_hidden; /* * Frees an object */ void object_heap_free(object_heap_p heap, object_base_p obj) attribute_hidden; /* * Destroys a heap, the heap must be empty. */ void object_heap_destroy(object_heap_p heap) attribute_hidden; #endif /* VA_OBJECT_HEAP_H */ vdpau-driver-0.7.4/src/put_bits.h000066400000000000000000000066631203356434100167370ustar00rootroot00000000000000/* * copyright (c) 2004 Michael Niedermayer * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PUT_BITS_H #define PUT_BITS_H #ifdef WORDS_BIGENDIAN #define be2me_32(x) (x) #else #define be2me_32(x) bswap_32(x) #endif #ifndef bswap_32 static inline uint32_t bswap_32(uint32_t x) { x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); x = (x >> 16) | (x << 16); return x; } #endif typedef struct PutBitContext { uint32_t bit_buf; int bit_left; uint8_t *buf; uint8_t *buf_ptr; uint8_t *buf_end; int size_in_bits; } PutBitContext; /** * Initializes the PutBitContext s. * * @param buffer the buffer where to put bits * @param buffer_size the size in bytes of buffer */ static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size) { if (buffer_size < 0) { buffer_size = 0; buffer = NULL; } s->size_in_bits = 8 * buffer_size; s->buf = buffer; s->buf_end = s->buf + buffer_size; s->buf_ptr = s->buf; s->bit_left = 32; s->bit_buf = 0; } /** * Returns the total number of bits written to the bitstream. */ static inline int put_bits_count(PutBitContext *s) { return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; } /** * Pads the end of the output stream with zeros. */ static inline void flush_put_bits(PutBitContext *s) { s->bit_buf <<= s->bit_left; while (s->bit_left < 32) { /* XXX: should test end of buffer */ *s->buf_ptr++ = s->bit_buf >> 24; s->bit_buf <<= 8; s->bit_left += 8; } s->bit_left = 32; s->bit_buf = 0; } /** * Write up to 31 bits into a bitstream. * Use put_bits32 to write 32 bits. */ static inline void put_bits(PutBitContext *s, int n, unsigned int value) { unsigned int bit_buf; int bit_left; assert(n <= 31 && value < (1U << n)); bit_buf = s->bit_buf; bit_left = s->bit_left; if (n < bit_left) { bit_buf = (bit_buf << n) | value; bit_left -= n; } else { bit_buf <<= bit_left; bit_buf |= value >> (n - bit_left); if (3 & (uintptr_t)s->buf_ptr) { s->buf_ptr[0] = bit_buf >> 24; s->buf_ptr[1] = bit_buf >> 16; s->buf_ptr[2] = bit_buf >> 8; s->buf_ptr[3] = bit_buf; } else *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); s->buf_ptr += 4; bit_left += 32 - n; bit_buf = value; } s->bit_buf = bit_buf; s->bit_left = bit_left; } /** * Pads the bitstream with zeros up to the next byte boundary. */ static inline void align_put_bits(PutBitContext *s) { put_bits(s, s->bit_left & 7, 0); } #endif /* PUT_BITS_H */ vdpau-driver-0.7.4/src/sysdeps.h000066400000000000000000000035531203356434100165730ustar00rootroot00000000000000/* * sysdeps.h - System dependent definitions * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef SYSDEPS_H #define SYSDEPS_H #include "config.h" #include #include #include #include #include // Helper macros #undef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #undef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #undef ARRAY_ELEMS #define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) #ifdef HAVE_VISIBILITY_ATTRIBUTE # define attribute_hidden __attribute__((__visibility__("hidden"))) #else # define attribute_hidden #endif #undef ASSERT #if USE_DEBUG # define ASSERT assert #else # define ASSERT(expr) do { \ if (!(expr)) { \ vdpau_error_message("Assertion failed in file %s at line %d\n", \ __FILE__, __LINE__); \ abort(); \ } \ } while (0) #endif #endif /* SYSDEPS_H */ vdpau-driver-0.7.4/src/uasyncqueue.c000066400000000000000000000061461203356434100174440ustar00rootroot00000000000000/* * uasyncqueue.c - Asynchronous queues * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "uasyncqueue.h" #include "uqueue.h" #include struct _UAsyncQueue { UQueue *queue; pthread_mutex_t mutex; pthread_cond_t cond; unsigned int is_waiting; }; UAsyncQueue *async_queue_new(void) { UAsyncQueue *queue = malloc(sizeof(*queue)); if (!queue) return NULL; queue->queue = queue_new(); if (!queue->queue) goto error; if (pthread_cond_init(&queue->cond, NULL) != 0) goto error; pthread_mutex_init(&queue->mutex, NULL); queue->is_waiting = 0; return queue; error: async_queue_free(queue); return NULL; } void async_queue_free(UAsyncQueue *queue) { if (!queue) return; pthread_mutex_unlock(&queue->mutex); queue_free(queue->queue); free(queue); } int async_queue_is_empty(UAsyncQueue *queue) { return queue && queue_is_empty(queue->queue); } static UAsyncQueue *async_queue_push_unlocked(UAsyncQueue *queue, void *data) { queue_push(queue->queue, data); if (queue->is_waiting) pthread_cond_signal(&queue->cond); return queue; } UAsyncQueue *async_queue_push(UAsyncQueue *queue, void *data) { if (!queue) return NULL; pthread_mutex_lock(&queue->mutex); async_queue_push_unlocked(queue, data); pthread_mutex_unlock(&queue->mutex); return queue; } static void * async_queue_timed_pop_unlocked(UAsyncQueue *queue, uint64_t end_time) { if (queue_is_empty(queue->queue)) { assert(!queue->is_waiting); ++queue->is_waiting; if (!end_time) pthread_cond_wait(&queue->cond, &queue->mutex); else { struct timespec timeout; timeout.tv_sec = end_time / 1000000; timeout.tv_nsec = 1000 * (end_time % 1000000); pthread_cond_timedwait(&queue->cond, &queue->mutex, &timeout); } --queue->is_waiting; if (queue_is_empty(queue->queue)) return NULL; } return queue_pop(queue->queue); } void *async_queue_timed_pop(UAsyncQueue *queue, uint64_t end_time) { void *data; if (!queue) return NULL; pthread_mutex_lock(&queue->mutex); data = async_queue_timed_pop_unlocked(queue, end_time); pthread_mutex_unlock(&queue->mutex); return data; } vdpau-driver-0.7.4/src/uasyncqueue.h000066400000000000000000000025631203356434100174500ustar00rootroot00000000000000/* * uasyncqueue.h - Asynchronous queues * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef UASYNCQUEUE_H #define UASYNCQUEUE_H typedef struct _UAsyncQueue UAsyncQueue; UAsyncQueue *async_queue_new(void) attribute_hidden; void async_queue_free(UAsyncQueue *queue) attribute_hidden; int async_queue_is_empty(UAsyncQueue *queue) attribute_hidden; UAsyncQueue *async_queue_push(UAsyncQueue *queue, void *data) attribute_hidden; void *async_queue_timed_pop(UAsyncQueue *queue, uint64_t end_time) attribute_hidden; #define async_queue_pop(queue) \ async_queue_timed_pop(queue, 0) #endif /* UASYNCQUEUE_H */ vdpau-driver-0.7.4/src/ulist.c000066400000000000000000000046351203356434100162360ustar00rootroot00000000000000/* * ulist.c - Lists * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "ulist.h" static UList *list_new(void *data, UList *prev, UList *next) { UList *list = malloc(sizeof(*list)); if (list) { list->data = data; list->prev = prev; list->next = next; if (prev) prev->next = list; if (next) next->prev = list; } return list; } void list_free_1(UList *list) { free(list); } void list_free(UList *list) { while (list) { UList * const next = list->next; list_free_1(list); list = next; } } UList *list_append(UList *list, void *data) { UList * const node = list_new(data, list_last(list), NULL); return list ? list : node; } UList *list_prepend(UList *list, void *data) { return list_new(data, list ? list->prev : NULL, list); } UList *list_first(UList *list) { if (list) { while (list->prev) list = list->prev; } return list; } UList *list_last(UList *list) { if (list) { while (list->next) list = list->next; } return list; } unsigned int list_size(UList *list) { unsigned int size = 0; while (list) { ++size; list = list->next; } return size; } UList *list_lookup_full(UList *list, const void *data, UListCompareFunc compare) { if (!list) return NULL; if (compare) { for (; list; list = list->next) if (compare(list->data, data)) return list; } else { for (; list; list = list->next) if (list->data == data) return list; } return NULL; } vdpau-driver-0.7.4/src/ulist.h000066400000000000000000000031511203356434100162330ustar00rootroot00000000000000/* * ulist.h - Lists * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef ULIST_H #define ULIST_H typedef struct _UList UList; struct _UList { void *data; UList *prev; UList *next; }; typedef int (*UListCompareFunc)(const void *a, const void *b); void list_free_1(UList *list) attribute_hidden; void list_free(UList *list) attribute_hidden; UList *list_append(UList *list, void *data) attribute_hidden; UList *list_prepend(UList *list, void *data) attribute_hidden; UList *list_first(UList *list) attribute_hidden; UList *list_last(UList *list) attribute_hidden; unsigned int list_size(UList *list) attribute_hidden; UList *list_lookup_full(UList *list, const void *data, UListCompareFunc compare) attribute_hidden; #define list_lookup(list, data) \ list_lookup_full(list, data, NULL) #endif /* ULIST_H */ vdpau-driver-0.7.4/src/uqueue.c000066400000000000000000000033631203356434100164040ustar00rootroot00000000000000/* * uqueue.c - Queues * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "uqueue.h" #include "ulist.h" struct _UQueue { UList *head; UList *tail; unsigned int size; }; UQueue *queue_new(void) { return calloc(1, sizeof(UQueue)); } void queue_free(UQueue *queue) { if (!queue) return; list_free(queue->head); free(queue); } int queue_is_empty(UQueue *queue) { return !queue || queue->size == 0; } UQueue *queue_push(UQueue *queue, void *data) { if (!queue) return NULL; queue->tail = list_last(list_append(queue->tail, data)); if (!queue->head) queue->head = queue->tail; ++queue->size; return queue; } void *queue_pop(UQueue *queue) { UList *list; void *data; if (!queue || !queue->head) return NULL; list = queue->head; data = list->data; queue->head = list->next; if (--queue->size == 0) queue->tail = NULL; list_free_1(list); return data; } vdpau-driver-0.7.4/src/uqueue.h000066400000000000000000000022551203356434100164100ustar00rootroot00000000000000/* * uqueue.h - Queues * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef UQUEUE_H #define UQUEUE_H typedef struct _UQueue UQueue; UQueue *queue_new(void) attribute_hidden; void queue_free(UQueue *queue) attribute_hidden; int queue_is_empty(UQueue *queue) attribute_hidden; UQueue *queue_push(UQueue *queue, void *data) attribute_hidden; void *queue_pop(UQueue *queue) attribute_hidden; #endif /* UQUEUE_H */ vdpau-driver-0.7.4/src/utils.c000066400000000000000000000126561203356434100162400ustar00rootroot00000000000000/* * utils.c - Utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "utils.h" #include #include #define DEBUG 1 #include "debug.h" // Parses ENV environment variable for an integer value int getenv_int(const char *env, int *pval) { const char *env_str = getenv(env); if (!env_str) return -1; char *end = NULL; long val = strtoul(env_str, &end, 10); if (end == NULL || end[0] != '\0') return -1; if (pval) *pval = val; return 0; } // Parses ENV environment variable expecting "yes" | "no" values int getenv_yesno(const char *env, int *pval) { const char *env_str = getenv(env); if (!env_str) return -1; int val; if (strcmp(env_str, "1") == 0 || strcmp(env_str, "yes") == 0) val = 1; else if (strcmp(env_str, "0") == 0 || strcmp(env_str, "no") == 0) val = 0; else return -1; if (pval) *pval = val; return 0; } // Get current value of microsecond timer uint64_t get_ticks_usec(void) { #ifdef HAVE_CLOCK_GETTIME struct timespec t; clock_gettime(CLOCK_REALTIME, &t); return (uint64_t)t.tv_sec * 1000000 + t.tv_nsec / 1000; #else struct timeval t; gettimeofday(&t, NULL); return (uint64_t)t.tv_sec * 1000000 + t.tv_usec; #endif } #if defined(__linux__) // Linux select() changes its timeout parameter upon return to contain // the remaining time. Most other unixen leave it unchanged or undefined. #define SELECT_SETS_REMAINING #elif defined(__FreeBSD__) || defined(__sun__) || (defined(__MACH__) && defined(__APPLE__)) #define USE_NANOSLEEP #elif defined(HAVE_PTHREADS) && defined(sgi) // SGI pthreads has a bug when using pthreads+signals+nanosleep, // so instead of using nanosleep, wait on a CV which is never signalled. #include #define USE_COND_TIMEDWAIT #endif // Wait for the specified amount of microseconds void delay_usec(unsigned int usec) { int was_error; #if defined(USE_NANOSLEEP) struct timespec elapsed, tv; #elif defined(USE_COND_TIMEDWAIT) // Use a local mutex and cv, so threads remain independent pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER; struct timespec elapsed; uint64_t future; #else struct timeval tv; #ifndef SELECT_SETS_REMAINING uint64_t then, now, elapsed; #endif #endif // Set the timeout interval - Linux only needs to do this once #if defined(SELECT_SETS_REMAINING) tv.tv_sec = 0; tv.tv_usec = usec; #elif defined(USE_NANOSLEEP) elapsed.tv_sec = 0; elapsed.tv_nsec = usec * 1000; #elif defined(USE_COND_TIMEDWAIT) future = get_ticks_usec() + usec; elapsed.tv_sec = future / 1000000; elapsed.tv_nsec = (future % 1000000) * 1000; #else then = get_ticks_usec(); #endif do { errno = 0; #if defined(USE_NANOSLEEP) tv.tv_sec = elapsed.tv_sec; tv.tv_nsec = elapsed.tv_nsec; was_error = nanosleep(&tv, &elapsed); #elif defined(USE_COND_TIMEDWAIT) was_error = pthread_mutex_lock(&delay_mutex); was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed); was_error = pthread_mutex_unlock(&delay_mutex); #else #ifndef SELECT_SETS_REMAINING // Calculate the time interval left (in case of interrupt) now = get_ticks_usec(); elapsed = now - then; then = now; if (elapsed >= usec) break; usec -= elapsed; tv.tv_sec = 0; tv.tv_usec = usec; #endif was_error = select(0, NULL, NULL, NULL, &tv); #endif } while (was_error && (errno == EINTR)); } // Reallocates a BUFFER to NUM_ELEMENTS of ELEMENT_SIZE bytes void * realloc_buffer( void **buffer_p, unsigned int *max_elements_p, unsigned int num_elements, unsigned int element_size ) { if (!buffer_p || !max_elements_p) return NULL; void *buffer = *buffer_p; if (*max_elements_p > num_elements) return buffer; num_elements += 4; if ((buffer = realloc(buffer, num_elements * element_size)) == NULL) { free(*buffer_p); *buffer_p = NULL; return NULL; } memset((uint8_t *)buffer + *max_elements_p * element_size, 0, (num_elements - *max_elements_p) * element_size); *buffer_p = buffer; *max_elements_p = num_elements; return buffer; } // Lookup for substring NAME in string EXT using SEP as separators int find_string(const char *name, const char *ext, const char *sep) { const char *end; int name_len, n; if (name == NULL || ext == NULL) return 0; end = ext + strlen(ext); name_len = strlen(name); while (ext < end) { n = strcspn(ext, sep); if (n == name_len && strncmp(name, ext, n) == 0) return 1; ext += (n + 1); } return 0; } vdpau-driver-0.7.4/src/utils.h000066400000000000000000000025541203356434100162410ustar00rootroot00000000000000/* * utils.h - Utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef UTILS_H #define UTILS_H int getenv_int(const char *env, int *pval) attribute_hidden; int getenv_yesno(const char *env, int *pval) attribute_hidden; uint64_t get_ticks_usec(void) attribute_hidden; void delay_usec(unsigned int usec) attribute_hidden; void * realloc_buffer( void **buffer_p, unsigned int *max_elements_p, unsigned int num_elements, unsigned int element_size ) attribute_hidden; int find_string(const char *name, const char *ext, const char *sep) attribute_hidden; #endif /* UTILS_H */ vdpau-driver-0.7.4/src/utils_glx.c000066400000000000000000001136611203356434100171100ustar00rootroot00000000000000/* * utils_glx.c - GLX utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #define _GNU_SOURCE 1 /* RTLD_DEFAULT */ #include "sysdeps.h" #include #include #include #include #include "utils.h" #include "utils_glx.h" #include "utils_x11.h" #define DEBUG 1 #include "debug.h" /** * gl_get_error_string: * @error: an OpenGL error enumeration * * Retrieves the string representation the OpenGL @error. * * Return error: the static string representing the OpenGL @error */ const char * gl_get_error_string(GLenum error) { static const struct { GLenum val; const char *str; } gl_errors[] = { { GL_NO_ERROR, "no error" }, { GL_INVALID_ENUM, "invalid enumerant" }, { GL_INVALID_VALUE, "invalid value" }, { GL_INVALID_OPERATION, "invalid operation" }, { GL_STACK_OVERFLOW, "stack overflow" }, { GL_STACK_UNDERFLOW, "stack underflow" }, { GL_OUT_OF_MEMORY, "out of memory" }, #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" }, #endif { ~0, NULL } }; unsigned int i; for (i = 0; gl_errors[i].str; i++) { if (gl_errors[i].val == error) return gl_errors[i].str; } return "unknown"; } /** * gl_purge_errors: * * Purges all OpenGL errors. This function is generally useful to * clear up the pending errors prior to calling gl_check_error(). */ void gl_purge_errors(void) { while (glGetError() != GL_NO_ERROR) ; /* nothing */ } /** * gl_check_error: * * Checks whether there is any OpenGL error pending. * * Return value: 1 if an error was encountered */ int gl_check_error(void) { GLenum error; int has_errors = 0; while ((error = glGetError()) != GL_NO_ERROR) { D(bug("glError: %s caught", gl_get_error_string(error))); has_errors = 1; } return has_errors; } /** * gl_get_current_color: * @color: the RGBA color components * * This function is a wrapper around glGetFloatv() that does extra error checking. * * Return value: 1 on success */ int gl_get_current_color(float color[4]) { gl_purge_errors(); glGetFloatv(GL_CURRENT_COLOR, color); return gl_check_error(); } /** * gl_get_param: * @param: the parameter name * @pval: return location for the value * * This function is a wrapper around glGetIntegerv() that does extra * error checking. * * Return value: 1 on success */ int gl_get_param(GLenum param, unsigned int *pval) { GLint val; gl_purge_errors(); glGetIntegerv(param, &val); if (gl_check_error()) return 0; if (pval) *pval = val; return 1; } /** * gl_get_texture_param: * @target: the target to which the texture is bound * @param: the parameter name * @pval: return location for the value * * This function is a wrapper around glGetTexLevelParameteriv() that * does extra error checking. * * Return value: 1 on success */ int gl_get_texture_param(GLenum target, GLenum param, unsigned int *pval) { GLint val; gl_purge_errors(); glGetTexLevelParameteriv(target, 0, param, &val); if (gl_check_error()) return 0; if (pval) *pval = val; return 1; } /** * gl_set_bgcolor: * @color: the requested RGB color * * Sets background color to the RGB @color. This basically is a * wrapper around glClearColor(). */ void gl_set_bgcolor(uint32_t color) { glClearColor( ((color >> 16) & 0xff) / 255.0f, ((color >> 8) & 0xff) / 255.0f, ( color & 0xff) / 255.0f, 1.0f ); } /** * gl_set_texture_scaling: * @target: the target to which the texture is currently bound * @scale: scaling algorithm * * Sets scaling algorithm used for the texture currently bound. */ void gl_set_texture_scaling(GLenum target, GLenum scale) { glTexParameteri(target, GL_TEXTURE_MIN_FILTER, scale); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, scale); } /** * gl_perspective: * @fovy: the field of view angle, in degrees, in the y direction * @aspect: the aspect ratio that determines the field of view in the * x direction. The aspect ratio is the ratio of x (width) to y * (height) * @zNear: the distance from the viewer to the near clipping plane * (always positive) * @zFar: the distance from the viewer to the far clipping plane * (always positive) * * Specified a viewing frustum into the world coordinate system. This * basically is the Mesa implementation of gluPerspective(). */ static void frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval) { GLdouble x, y, a, b, c, d; GLdouble m[16]; x = (2.0 * nearval) / (right - left); y = (2.0 * nearval) / (top - bottom); a = (right + left) / (right - left); b = (top + bottom) / (top - bottom); c = -(farval + nearval) / ( farval - nearval); d = -(2.0 * farval * nearval) / (farval - nearval); #define M(row,col) m[col*4+row] M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; #undef M glMultMatrixd(m); } static void gl_perspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { GLdouble xmin, xmax, ymin, ymax; ymax = zNear * tan(fovy * M_PI / 360.0); ymin = -ymax; xmin = ymin * aspect; xmax = ymax * aspect; /* Don't call glFrustum() because of error semantics (covglu) */ frustum(xmin, xmax, ymin, ymax, zNear, zFar); } /** * gl_resize: * @width: the requested width, in pixels * @height: the requested height, in pixels * * Resizes the OpenGL viewport to the specified dimensions, using an * orthogonal projection. (0,0) represents the top-left corner of the * window. */ void gl_resize(unsigned int width, unsigned int height) { #define FOVY 60.0f #define ASPECT 1.0f #define Z_NEAR 0.1f #define Z_FAR 100.0f #define Z_CAMERA 0.869f glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gl_perspective(FOVY, ASPECT, Z_NEAR, Z_FAR); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-0.5f, -0.5f, -Z_CAMERA); glScalef(1.0f/width, -1.0f/height, 1.0f/width); glTranslatef(0.0f, -1.0f*height, 0.0f); } /** * gl_create_context: * @dpy: an X11 #Display * @screen: the associated screen of @dpy * @parent: the parent #GLContextState, or %NULL if none is to be used * * Creates a GLX context sharing textures and displays lists with * @parent, if not %NULL. * * Return value: the newly created GLX context */ GLContextState * gl_create_context(Display *dpy, int screen, GLContextState *parent) { GLContextState *cs; GLXFBConfig *fbconfigs = NULL; int fbconfig_id, val, n, n_fbconfigs; Status status; static GLint fbconfig_attrs[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DOUBLEBUFFER, True, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None }; cs = malloc(sizeof(*cs)); if (!cs) goto error; cs->display = dpy; cs->window = parent ? parent->window : None; cs->visual = NULL; cs->context = NULL; if (parent && parent->context) { status = glXQueryContext( parent->display, parent->context, GLX_FBCONFIG_ID, &fbconfig_id ); if (status != Success) goto error; fbconfigs = glXGetFBConfigs(dpy, screen, &n_fbconfigs); if (!fbconfigs) goto error; /* Find out a GLXFBConfig compatible with the parent context */ for (n = 0; n < n_fbconfigs; n++) { status = glXGetFBConfigAttrib( dpy, fbconfigs[n], GLX_FBCONFIG_ID, &val ); if (status == Success && val == fbconfig_id) break; } if (n == n_fbconfigs) goto error; } else { fbconfigs = glXChooseFBConfig( dpy, screen, fbconfig_attrs, &n_fbconfigs ); if (!fbconfigs) goto error; /* Select the first one */ n = 0; } cs->visual = glXGetVisualFromFBConfig(dpy, fbconfigs[n]); cs->context = glXCreateNewContext( dpy, fbconfigs[n], GLX_RGBA_TYPE, parent ? parent->context : NULL, True ); if (cs->context) goto end; error: gl_destroy_context(cs); cs = NULL; end: if (fbconfigs) XFree(fbconfigs); return cs; } /** * gl_destroy_context: * @cs: a #GLContextState * * Destroys the GLX context @cs */ void gl_destroy_context(GLContextState *cs) { if (!cs) return; if (cs->visual) { XFree(cs->visual); cs->visual = NULL; } if (cs->display && cs->context) { if (glXGetCurrentContext() == cs->context) glXMakeCurrent(cs->display, None, NULL); glXDestroyContext(cs->display, cs->context); cs->display = NULL; cs->context = NULL; } free(cs); } /** * gl_init_context: * @cs: a #GLContextState * * Initializes the GLX context @cs with a base environment. */ void gl_init_context(GLContextState *cs) { GLContextState old_cs, tmp_cs; if (!gl_set_current_context(cs, &old_cs)) return; glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glDisable(GL_CULL_FACE); glDrawBuffer(GL_BACK); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_set_current_context(&old_cs, &tmp_cs); } /** * gl_get_current_context: * @cs: return location to the current #GLContextState * * Retrieves the current GLX context, display and drawable packed into * the #GLContextState struct. */ void gl_get_current_context(GLContextState *cs) { cs->display = glXGetCurrentDisplay(); cs->window = glXGetCurrentDrawable(); cs->context = glXGetCurrentContext(); } /** * gl_set_current_context: * @new_cs: the requested new #GLContextState * @old_cs: return location to the context that was previously current * * Makes the @new_cs GLX context the current GLX rendering context of * the calling thread, replacing the previously current context if * there was one. * * If @old_cs is non %NULL, the previously current GLX context and * window are recorded. * * Return value: 1 on success */ int gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs) { /* If display is NULL, this could be that new_cs was retrieved from gl_get_current_context() with none set previously. If that case, the other fields are also NULL and we don't return an error */ if (!new_cs->display) return !new_cs->window && !new_cs->context; if (old_cs) { if (old_cs == new_cs) return 1; gl_get_current_context(old_cs); if (old_cs->display == new_cs->display && old_cs->window == new_cs->window && old_cs->context == new_cs->context) return 1; } return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context); } /** * gl_swap_buffers: * @cs: a #GLContextState * * Promotes the contents of the back buffer of the @win window to * become the contents of the front buffer. This simply is wrapper * around glXSwapBuffers(). */ void gl_swap_buffers(GLContextState *cs) { glXSwapBuffers(cs->display, cs->window); } /** * gl_create_texture: * @target: the target to which the texture is bound * @format: the format of the pixel data * @width: the requested width, in pixels * @height: the requested height, in pixels * * Creates a texture with the specified dimensions and @format. The * internal format will be automatically derived from @format. * * Return value: the newly created texture name */ GLuint gl_create_texture(GLenum target, GLenum format, unsigned int width, unsigned int height) { GLVTable * const gl_vtable = gl_get_vtable(); GLenum internal_format; GLuint texture; unsigned int bytes_per_component; switch (target) { case GL_TEXTURE_2D: if (!gl_vtable->has_texture_non_power_of_two) { D(bug("Unsupported GL_ARB_texture_non_power_of_two extension\n")); return 0; } break; case GL_TEXTURE_RECTANGLE_ARB: if (!gl_vtable->has_texture_rectangle) { D(bug("Unsupported GL_ARB_texture_rectangle extension\n")); return 0; } break; default: D(bug("Unsupported texture target 0x%04x\n", target)); return 0; } internal_format = format; switch (format) { case GL_LUMINANCE: bytes_per_component = 1; break; case GL_LUMINANCE_ALPHA: bytes_per_component = 2; break; case GL_RGBA: case GL_BGRA: internal_format = GL_RGBA; bytes_per_component = 4; break; default: bytes_per_component = 0; break; } ASSERT(bytes_per_component > 0); glEnable(target); glGenTextures(1, &texture); glBindTexture(target, texture); gl_set_texture_scaling(target, GL_LINEAR); glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ALIGNMENT, bytes_per_component); glTexImage2D( target, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL ); glBindTexture(target, 0); return texture; } /** * get_proc_address: * @name: the name of the OpenGL extension function to lookup * * Returns the specified OpenGL extension function * * Return value: the OpenGL extension matching @name, or %NULL if none * was found */ typedef void (*GLFuncPtr)(void); typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *); static GLFuncPtr get_proc_address_default(const char *name) { return NULL; } static GLXGetProcAddressProc get_proc_address_func(void) { GLXGetProcAddressProc get_proc_func; dlerror(); get_proc_func = (GLXGetProcAddressProc) dlsym(RTLD_DEFAULT, "glXGetProcAddress"); if (!dlerror()) return get_proc_func; get_proc_func = (GLXGetProcAddressProc) dlsym(RTLD_DEFAULT, "glXGetProcAddressARB"); if (!dlerror()) return get_proc_func; return get_proc_address_default; } static inline GLFuncPtr get_proc_address(const char *name) { static GLXGetProcAddressProc get_proc_func = NULL; if (!get_proc_func) get_proc_func = get_proc_address_func(); return get_proc_func(name); } /** * gl_init_vtable: * * Initializes the global #GLVTable. * * Return value: the #GLVTable filled in with OpenGL extensions, or * %NULL on error. */ static GLVTable gl_vtable_static; static GLVTable * gl_init_vtable(void) { GLVTable * const gl_vtable = &gl_vtable_static; const char *gl_extensions = (const char *)glGetString(GL_EXTENSIONS); int has_extension; /* GL_ARB_texture_non_power_of_two */ has_extension = ( find_string("GL_ARB_texture_non_power_of_two", gl_extensions, " ") ); if (has_extension) gl_vtable->has_texture_non_power_of_two = 1; /* GL_ARB_texture_rectangle */ has_extension = ( find_string("GL_ARB_texture_rectangle", gl_extensions, " ") ); if (has_extension) gl_vtable->has_texture_rectangle = 1; /* GLX_EXT_texture_from_pixmap */ gl_vtable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC) get_proc_address("glXBindTexImageEXT"); if (!gl_vtable->glx_bind_tex_image) return NULL; gl_vtable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC) get_proc_address("glXReleaseTexImageEXT"); if (!gl_vtable->glx_release_tex_image) return NULL; /* GL_ARB_framebuffer_object */ has_extension = ( find_string("GL_ARB_framebuffer_object", gl_extensions, " ") || find_string("GL_EXT_framebuffer_object", gl_extensions, " ") ); if (has_extension) { gl_vtable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) get_proc_address("glGenFramebuffersEXT"); if (!gl_vtable->gl_gen_framebuffers) return NULL; gl_vtable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) get_proc_address("glDeleteFramebuffersEXT"); if (!gl_vtable->gl_delete_framebuffers) return NULL; gl_vtable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) get_proc_address("glBindFramebufferEXT"); if (!gl_vtable->gl_bind_framebuffer) return NULL; gl_vtable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC) get_proc_address("glGenRenderbuffersEXT"); if (!gl_vtable->gl_gen_renderbuffers) return NULL; gl_vtable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC) get_proc_address("glDeleteRenderbuffersEXT"); if (!gl_vtable->gl_delete_renderbuffers) return NULL; gl_vtable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC) get_proc_address("glBindRenderbufferEXT"); if (!gl_vtable->gl_bind_renderbuffer) return NULL; gl_vtable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC) get_proc_address("glRenderbufferStorageEXT"); if (!gl_vtable->gl_renderbuffer_storage) return NULL; gl_vtable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) get_proc_address("glFramebufferRenderbufferEXT"); if (!gl_vtable->gl_framebuffer_renderbuffer) return NULL; gl_vtable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) get_proc_address("glFramebufferTexture2DEXT"); if (!gl_vtable->gl_framebuffer_texture_2d) return NULL; gl_vtable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) get_proc_address("glCheckFramebufferStatusEXT"); if (!gl_vtable->gl_check_framebuffer_status) return NULL; gl_vtable->has_framebuffer_object = 1; } /* GL_ARB_fragment_program */ has_extension = ( find_string("GL_ARB_fragment_program", gl_extensions, " ") ); if (has_extension) { gl_vtable->gl_gen_programs = (PFNGLGENPROGRAMSARBPROC) get_proc_address("glGenProgramsARB"); if (!gl_vtable->gl_gen_programs) return NULL; gl_vtable->gl_delete_programs = (PFNGLDELETEPROGRAMSARBPROC) get_proc_address("glDeleteProgramsARB"); if (!gl_vtable->gl_delete_programs) return NULL; gl_vtable->gl_bind_program = (PFNGLBINDPROGRAMARBPROC) get_proc_address("glBindProgramARB"); if (!gl_vtable->gl_bind_program) return NULL; gl_vtable->gl_program_string = (PFNGLPROGRAMSTRINGARBPROC) get_proc_address("glProgramStringARB"); if (!gl_vtable->gl_program_string) return NULL; gl_vtable->gl_get_program_iv = (PFNGLGETPROGRAMIVARBPROC) get_proc_address("glGetProgramivARB"); if (!gl_vtable->gl_get_program_iv) return NULL; gl_vtable->gl_program_local_parameter_4fv = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) get_proc_address("glProgramLocalParameter4fvARB"); if (!gl_vtable->gl_program_local_parameter_4fv) return NULL; gl_vtable->has_fragment_program = 1; } /* GL_ARB_multitexture */ has_extension = ( find_string("GL_ARB_multitexture", gl_extensions, " ") ); if (has_extension) { gl_vtable->gl_active_texture = (PFNGLACTIVETEXTUREPROC) get_proc_address("glActiveTextureARB"); if (!gl_vtable->gl_active_texture) return NULL; gl_vtable->gl_multi_tex_coord_2f = (PFNGLMULTITEXCOORD2FPROC) get_proc_address("glMultiTexCoord2fARB"); if (!gl_vtable->gl_multi_tex_coord_2f) return NULL; gl_vtable->has_multitexture = 1; } /* GL_NV_vdpau_interop */ has_extension = ( find_string("GL_NV_vdpau_interop", gl_extensions, " ") ); if (has_extension) { gl_vtable->gl_vdpau_init = (PFNGLVDPAUINITNVPROC) get_proc_address("glVDPAUInitNV"); if (!gl_vtable->gl_vdpau_init) return NULL; gl_vtable->gl_vdpau_fini = (PFNGLVDPAUFININVPROC) get_proc_address("glVDPAUFiniNV"); if (!gl_vtable->gl_vdpau_fini) return NULL; gl_vtable->gl_vdpau_register_video_surface = (PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) get_proc_address("glVDPAURegisterVideoSurfaceNV"); if (!gl_vtable->gl_vdpau_register_video_surface) return NULL; gl_vtable->gl_vdpau_register_output_surface = (PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) get_proc_address("glVDPAURegisterOutputSurfaceNV"); if (!gl_vtable->gl_vdpau_register_output_surface) return NULL; gl_vtable->gl_vdpau_is_surface = (PFNGLVDPAUISSURFACENVPROC) get_proc_address("glVDPAUIsSurfaceNV"); if (!gl_vtable->gl_vdpau_is_surface) return NULL; gl_vtable->gl_vdpau_unregister_surface = (PFNGLVDPAUUNREGISTERSURFACENVPROC) get_proc_address("glVDPAUUnregisterSurfaceNV"); if (!gl_vtable->gl_vdpau_unregister_surface) return NULL; gl_vtable->gl_vdpau_get_surface_iv = (PFNGLVDPAUGETSURFACEIVNVPROC) get_proc_address("glVDPAUGetSurfaceivNV"); if (!gl_vtable->gl_vdpau_get_surface_iv) return NULL; gl_vtable->gl_vdpau_surface_access = (PFNGLVDPAUSURFACEACCESSNVPROC) get_proc_address("glVDPAUSurfaceAccessNV"); if (!gl_vtable->gl_vdpau_surface_access) return NULL; gl_vtable->gl_vdpau_map_surfaces = (PFNGLVDPAUMAPSURFACESNVPROC) get_proc_address("glVDPAUMapSurfacesNV"); if (!gl_vtable->gl_vdpau_map_surfaces) return NULL; gl_vtable->gl_vdpau_unmap_surfaces = (PFNGLVDPAUUNMAPSURFACESNVPROC) get_proc_address("glVDPAUUnmapSurfacesNV"); if (!gl_vtable->gl_vdpau_unmap_surfaces) return NULL; gl_vtable->has_vdpau_interop = 1; } return gl_vtable; } /** * gl_get_vtable: * * Retrieves a VTable for OpenGL extensions. * * Return value: VTable for OpenGL extensions */ GLVTable * gl_get_vtable(void) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int gl_vtable_init = 1; static GLVTable *gl_vtable = NULL; pthread_mutex_lock(&mutex); if (gl_vtable_init) { gl_vtable_init = 0; gl_vtable = gl_init_vtable(); } pthread_mutex_unlock(&mutex); return gl_vtable; } /** * gl_create_pixmap_object: * @dpy: an X11 #Display * @target: the target to which the texture is bound * @width: the request width, in pixels * @height: the request height, in pixels * * Creates a #GLPixmapObject of the specified dimensions. This * requires the GLX_EXT_texture_from_pixmap extension. * * Return value: the newly created #GLPixmapObject object */ GLPixmapObject * gl_create_pixmap_object( Display *dpy, GLenum target, unsigned int width, unsigned int height ) { GLVTable * const gl_vtable = gl_get_vtable(); GLPixmapObject *pixo; GLXFBConfig *fbconfig; int screen; Window rootwin; XWindowAttributes wattr; int *attr; int n_fbconfig_attrs; int fbconfig_attrs[32] = { GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_DOUBLEBUFFER, GL_FALSE, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_RENDERABLE, GL_TRUE, GLX_Y_INVERTED_EXT, GL_TRUE, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GL_NONE, }; int pixmap_attrs[10] = { GLX_MIPMAP_TEXTURE_EXT, GL_FALSE, GL_NONE, }; if (!gl_vtable) return NULL; screen = DefaultScreen(dpy); rootwin = RootWindow(dpy, screen); /* XXX: this won't work for different displays */ if (!gl_vtable->has_texture_from_pixmap) { const char *glx_extensions; int glx_major, glx_minor; glx_extensions = glXQueryExtensionsString(dpy, screen); if (!glx_extensions) return NULL; if (!find_string("GLX_EXT_texture_from_pixmap", glx_extensions, " ")) return NULL; if (!glXQueryVersion(dpy, &glx_major, &glx_minor)) return NULL; if (glx_major < 1 || (glx_major == 1 && glx_minor < 3)) /* 1.3 */ return NULL; gl_vtable->has_texture_from_pixmap = 1; } pixo = calloc(1, sizeof(*pixo)); if (!pixo) return NULL; pixo->dpy = dpy; pixo->target = target; pixo->width = width; pixo->height = height; pixo->pixmap = None; pixo->glx_pixmap = None; pixo->is_bound = 0; XGetWindowAttributes(dpy, rootwin, &wattr); pixo->pixmap = XCreatePixmap(dpy, rootwin, width, height, wattr.depth); if (!pixo->pixmap) goto error; /* Initialize FBConfig attributes */ for (attr = fbconfig_attrs; *attr != GL_NONE; attr += 2) ; *attr++ = GLX_DEPTH_SIZE; *attr++ = wattr.depth; if (wattr.depth == 32) { *attr++ = GLX_ALPHA_SIZE; *attr++ = 8; *attr++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attr++ = GL_TRUE; } else { *attr++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attr++ = GL_TRUE; } *attr++ = GL_NONE; fbconfig = glXChooseFBConfig( dpy, screen, fbconfig_attrs, &n_fbconfig_attrs ); if (!fbconfig) goto error; /* Initialize GLX Pixmap attributes */ for (attr = pixmap_attrs; *attr != GL_NONE; attr += 2) ; *attr++ = GLX_TEXTURE_TARGET_EXT; switch (target) { case GL_TEXTURE_2D: *attr++ = GLX_TEXTURE_2D_EXT; break; case GL_TEXTURE_RECTANGLE_ARB: *attr++ = GLX_TEXTURE_RECTANGLE_EXT; break; default: goto error; } *attr++ = GLX_TEXTURE_FORMAT_EXT; if (wattr.depth == 32) *attr++ = GLX_TEXTURE_FORMAT_RGBA_EXT; else *attr++ = GLX_TEXTURE_FORMAT_RGB_EXT; *attr++ = GL_NONE; x11_trap_errors(); pixo->glx_pixmap = glXCreatePixmap(dpy, fbconfig[0], pixo->pixmap, pixmap_attrs); free(fbconfig); if (x11_untrap_errors() != 0) goto error; glEnable(pixo->target); glGenTextures(1, &pixo->texture); glBindTexture(pixo->target, pixo->texture); gl_set_texture_scaling(pixo->target, GL_LINEAR); glBindTexture(pixo->target, 0); return pixo; error: gl_destroy_pixmap_object(pixo); return NULL; } /** * gl_destroy_pixmap_object: * @pixo: a #GLPixmapObject * * Destroys the #GLPixmapObject object. */ void gl_destroy_pixmap_object(GLPixmapObject *pixo) { if (!pixo) return; gl_unbind_pixmap_object(pixo); if (pixo->texture) { glDeleteTextures(1, &pixo->texture); pixo->texture = 0; } if (pixo->glx_pixmap) { glXDestroyPixmap(pixo->dpy, pixo->glx_pixmap); pixo->glx_pixmap = None; } if (pixo->pixmap) { XFreePixmap(pixo->dpy, pixo->pixmap); pixo->pixmap = None; } free(pixo); } /** * gl_bind_pixmap_object: * @pixo: a #GLPixmapObject * * Defines a two-dimensional texture image. The texture image is taken * from the @pixo pixmap and need not be copied. The texture target, * format and size are derived from attributes of the @pixo pixmap. * * Return value: 1 on success */ int gl_bind_pixmap_object(GLPixmapObject *pixo) { GLVTable * const gl_vtable = gl_get_vtable(); if (pixo->is_bound) return 1; glBindTexture(pixo->target, pixo->texture); x11_trap_errors(); gl_vtable->glx_bind_tex_image( pixo->dpy, pixo->glx_pixmap, GLX_FRONT_LEFT_EXT, NULL ); XSync(pixo->dpy, False); if (x11_untrap_errors() != 0) { D(bug("failed to bind pixmap")); return 0; } pixo->is_bound = 1; return 1; } /** * gl_unbind_pixmap_object: * @pixo: a #GLPixmapObject * * Releases a color buffers that is being used as a texture. * * Return value: 1 on success */ int gl_unbind_pixmap_object(GLPixmapObject *pixo) { GLVTable * const gl_vtable = gl_get_vtable(); if (!pixo->is_bound) return 1; x11_trap_errors(); gl_vtable->glx_release_tex_image( pixo->dpy, pixo->glx_pixmap, GLX_FRONT_LEFT_EXT ); XSync(pixo->dpy, False); if (x11_untrap_errors() != 0) { D(bug("failed to release pixmap")); return 0; } glBindTexture(pixo->target, 0); pixo->is_bound = 0; return 1; } /** * gl_create_framebuffer_object: * @target: the target to which the texture is bound * @texture: the GL texture to hold the framebuffer * @width: the requested width, in pixels * @height: the requested height, in pixels * * Creates an FBO with the specified texture and size. * * Return value: the newly created #GLFramebufferObject, or %NULL if * an error occurred */ GLFramebufferObject * gl_create_framebuffer_object( GLenum target, GLuint texture, unsigned int width, unsigned int height ) { GLVTable * const gl_vtable = gl_get_vtable(); GLFramebufferObject *fbo; GLenum status; if (!gl_vtable || !gl_vtable->has_framebuffer_object) return NULL; fbo = calloc(1, sizeof(*fbo)); if (!fbo) return NULL; fbo->width = width; fbo->height = height; fbo->fbo = 0; fbo->old_fbo = 0; fbo->is_bound = 0; gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo); gl_vtable->gl_gen_framebuffers(1, &fbo->fbo); gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo); gl_vtable->gl_framebuffer_texture_2d( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, texture, 0 ); status = gl_vtable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT); gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) goto error; return fbo; error: gl_destroy_framebuffer_object(fbo); return NULL; } /** * gl_destroy_framebuffer_object: * @fbo: a #GLFramebufferObject * * Destroys the @fbo object. */ void gl_destroy_framebuffer_object(GLFramebufferObject *fbo) { GLVTable * const gl_vtable = gl_get_vtable(); if (!fbo) return; gl_unbind_framebuffer_object(fbo); if (fbo->fbo) { gl_vtable->gl_delete_framebuffers(1, &fbo->fbo); fbo->fbo = 0; } free(fbo); } /** * gl_bind_framebuffer_object: * @fbo: a #GLFramebufferObject * * Binds @fbo object. * * Return value: 1 on success */ int gl_bind_framebuffer_object(GLFramebufferObject *fbo) { GLVTable * const gl_vtable = gl_get_vtable(); const unsigned int width = fbo->width; const unsigned int height = fbo->height; const unsigned int attribs = (GL_VIEWPORT_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); if (fbo->is_bound) return 1; gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo); gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo); glPushAttrib(attribs); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glViewport(0, 0, width, height); glTranslatef(-1.0f, -1.0f, 0.0f); glScalef(2.0f / width, 2.0f / height, 1.0f); fbo->is_bound = 1; return 1; } /** * gl_unbind_framebuffer_object: * @fbo: a #GLFramebufferObject * * Releases @fbo object. * * Return value: 1 on success */ int gl_unbind_framebuffer_object(GLFramebufferObject *fbo) { GLVTable * const gl_vtable = gl_get_vtable(); if (!fbo->is_bound) return 1; glPopAttrib(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo); fbo->is_bound = 0; return 1; } /** * gl_vdpau_init: * @device: a #VdpDevice * @get_proc_address: the #VdpGetProcAddress generated during * #VdpDevice creation * * Informs the GL context which VDPAU device to interact with. * * Return value: 1 on success */ int gl_vdpau_init(VdpDevice device, VdpGetProcAddress get_proc_address) { GLVTable * const gl_vtable = gl_get_vtable(); if (!gl_vtable || !gl_vtable->has_vdpau_interop) return 0; gl_vtable->gl_vdpau_init((void *)(uintptr_t)device, get_proc_address); return 1; } /** * gl_vdpau_exit: * * Disposes the VDPAU/GL interact functionality for the current context. */ void gl_vdpau_exit(void) { GLVTable * const gl_vtable = gl_get_vtable(); if (!gl_vtable || !gl_vtable->has_vdpau_interop) return; gl_vtable->gl_vdpau_fini(); } /** * gl_vdpau_create_video_surface: * @target: the texture target * @surface: the VDPAU video surface to wrap * * Creates a VDPAU/GL surface from the specified @surface, which is a * #VdpVideoSurface. * * Return value: the newly created #GLVdpSurface, or %NULL if an error * occurred */ GLVdpSurface * gl_vdpau_create_video_surface(GLenum target, VdpVideoSurface surface) { GLVTable * const gl_vtable = gl_get_vtable(); GLVdpSurface *s; unsigned int i; if (!gl_vtable || !gl_vtable->has_vdpau_interop) return NULL; s = calloc(1, sizeof(*s)); if (!s) return NULL; s->target = target; s->num_textures = 4; s->is_bound = 0; glEnable(s->target); glGenTextures(s->num_textures, &s->textures[0]); s->surface = gl_vtable->gl_vdpau_register_video_surface( (void *)(uintptr_t)surface, s->target, s->num_textures, s->textures ); if (!s->surface) goto error; for (i = 0; i < s->num_textures; i++) { glBindTexture(s->target, s->textures[i]); gl_set_texture_scaling(s->target, GL_LINEAR); glTexParameteri(s->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(s->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(s->target, 0); } /* XXX: optimize for reading only */ gl_vtable->gl_vdpau_surface_access(s->surface, GL_READ_ONLY); return s; error: gl_vdpau_destroy_surface(s); return NULL; } /** * gl_vdpau_create_output_surface: * @target: the texture target * @surface: the VDPAU output surface to wrap * * Creates a VDPAU/GL surface from the specified @surface, which is a * #VdpOutputSurface. * * Return value: the newly created #GLVdpSurface, or %NULL if an error * occurred */ GLVdpSurface * gl_vdpau_create_output_surface(GLenum target, VdpOutputSurface surface) { GLVTable * const gl_vtable = gl_get_vtable(); GLVdpSurface *s; if (!gl_vtable || !gl_vtable->has_vdpau_interop) return NULL; s = calloc(1, sizeof(*s)); if (!s) return NULL; s->target = target; s->num_textures = 1; s->is_bound = 0; glEnable(s->target); glGenTextures(1, &s->textures[0]); s->surface = gl_vtable->gl_vdpau_register_output_surface( (void *)(uintptr_t)surface, s->target, s->num_textures, s->textures ); if (!s->surface) goto error; glBindTexture(s->target, s->textures[0]); gl_set_texture_scaling(s->target, GL_LINEAR); glBindTexture(s->target, 0); /* XXX: optimize for reading only */ gl_vtable->gl_vdpau_surface_access(s->surface, GL_READ_ONLY); return s; error: gl_vdpau_destroy_surface(s); return NULL; } /** * gl_vdpau_destroy_surface: * @s: a #GLVdpSurface * * Destroys the @s object. */ void gl_vdpau_destroy_surface(GLVdpSurface *s) { GLVTable * const gl_vtable = gl_get_vtable(); unsigned int i; if (!s) return; gl_vdpau_unbind_surface(s); if (s->surface) { gl_vtable->gl_vdpau_unregister_surface(s->surface); s->surface = 0; } if (s->num_textures > 0) { glDeleteTextures(s->num_textures, s->textures); for (i = 0; i < s->num_textures; i++) s->textures[i] = 0; s->num_textures = 0; } free(s); } /** * gl_vdpau_bind_surface: * @s: a #GLVdpSurface * * Binds surface @s. * * Return value: 1 on success */ int gl_vdpau_bind_surface(GLVdpSurface *s) { GLVTable * const gl_vtable = gl_get_vtable(); if (s->is_bound) return 1; gl_vtable->gl_vdpau_map_surfaces(1, &s->surface); s->is_bound = 1; return 1; } /** * gl_vdpau_unbind_surface: * @s: a #GLVdpSurface * * Releases surface @s. * * Return value: 1 on success */ int gl_vdpau_unbind_surface(GLVdpSurface *s) { GLVTable * const gl_vtable = gl_get_vtable(); if (!s->is_bound) return 1; gl_vtable->gl_vdpau_unmap_surfaces(1, &s->surface); s->is_bound = 0; return 1; } vdpau-driver-0.7.4/src/utils_glx.h000066400000000000000000000216641203356434100171160ustar00rootroot00000000000000/* * utils_glx.h - GLX utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef UTILS_GLX_H #define UTILS_GLX_H #include #include #include #include #include /* GL_NV_vdpau_interop */ #if GL_GLEXT_VERSION < 64 typedef GLintptr GLvdpauSurfaceNV; typedef void (*PFNGLVDPAUINITNVPROC)(const GLvoid *vdpDevice, const GLvoid *getProcAddress); typedef void (*PFNGLVDPAUFININVPROC)(void); typedef GLvdpauSurfaceNV (*PFNGLVDPAUREGISTERVIDEOSURFACENVPROC)(const GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); typedef GLvdpauSurfaceNV (*PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC)(const GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); typedef GLboolean (*PFNGLVDPAUISSURFACENVPROC)(GLvdpauSurfaceNV surface); typedef void (*PFNGLVDPAUUNREGISTERSURFACENVPROC)(GLvdpauSurfaceNV surface); typedef void (*PFNGLVDPAUGETSURFACEIVNVPROC)(GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); typedef void (*PFNGLVDPAUSURFACEACCESSNVPROC)(GLvdpauSurfaceNV surface, GLenum access); typedef void (*PFNGLVDPAUMAPSURFACESNVPROC)(GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); typedef void (*PFNGLVDPAUUNMAPSURFACESNVPROC)(GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); #endif /* GLX_EXT_texture_from_pixmap */ #if GLX_GLXEXT_VERSION < 18 typedef void (*PFNGLXBINDTEXIMAGEEXTPROC)(Display *, GLXDrawable, int, const int *); typedef void (*PFNGLXRELEASETEXIMAGEEXTPROC)(Display *, GLXDrawable, int); #endif #ifndef GL_FRAMEBUFFER_BINDING #define GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT #endif #ifndef GL_FRAGMENT_PROGRAM #define GL_FRAGMENT_PROGRAM GL_FRAGMENT_PROGRAM_ARB #endif #ifndef GL_PROGRAM_FORMAT_ASCII #define GL_PROGRAM_FORMAT_ASCII GL_PROGRAM_FORMAT_ASCII_ARB #endif #ifndef GL_PROGRAM_ERROR_POSITION #define GL_PROGRAM_ERROR_POSITION GL_PROGRAM_ERROR_POSITION_ARB #endif #ifndef GL_PROGRAM_ERROR_STRING #define GL_PROGRAM_ERROR_STRING GL_PROGRAM_ERROR_STRING_ARB #endif #ifndef GL_PROGRAM_UNDER_NATIVE_LIMITS #define GL_PROGRAM_UNDER_NATIVE_LIMITS GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB #endif const char * gl_get_error_string(GLenum error) attribute_hidden; void gl_purge_errors(void) attribute_hidden; int gl_check_error(void) attribute_hidden; int gl_get_current_color(float color[4]) attribute_hidden; int gl_get_param(GLenum param, unsigned int *pval) attribute_hidden; int gl_get_texture_param(GLenum target, GLenum param, unsigned int *pval) attribute_hidden; void gl_set_bgcolor(uint32_t color) attribute_hidden; void gl_set_texture_scaling(GLenum target, GLenum scale) attribute_hidden; void gl_resize(unsigned int width, unsigned int height) attribute_hidden; typedef struct _GLContextState GLContextState; struct _GLContextState { Display *display; Window window; XVisualInfo *visual; GLXContext context; }; GLContextState * gl_create_context(Display *dpy, int screen, GLContextState *parent) attribute_hidden; void gl_destroy_context(GLContextState *cs) attribute_hidden; void gl_init_context(GLContextState *cs) attribute_hidden; void gl_get_current_context(GLContextState *cs) attribute_hidden; int gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs) attribute_hidden; void gl_swap_buffers(GLContextState *cs) attribute_hidden; GLuint gl_create_texture(GLenum target, GLenum format, unsigned int width, unsigned int height) attribute_hidden; typedef struct _GLVTable GLVTable; struct _GLVTable { PFNGLXBINDTEXIMAGEEXTPROC glx_bind_tex_image; PFNGLXRELEASETEXIMAGEEXTPROC glx_release_tex_image; PFNGLGENFRAMEBUFFERSEXTPROC gl_gen_framebuffers; PFNGLDELETEFRAMEBUFFERSEXTPROC gl_delete_framebuffers; PFNGLBINDFRAMEBUFFEREXTPROC gl_bind_framebuffer; PFNGLGENRENDERBUFFERSEXTPROC gl_gen_renderbuffers; PFNGLDELETERENDERBUFFERSEXTPROC gl_delete_renderbuffers; PFNGLBINDRENDERBUFFEREXTPROC gl_bind_renderbuffer; PFNGLRENDERBUFFERSTORAGEEXTPROC gl_renderbuffer_storage; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC gl_framebuffer_renderbuffer; PFNGLFRAMEBUFFERTEXTURE2DEXTPROC gl_framebuffer_texture_2d; PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC gl_check_framebuffer_status; PFNGLGENPROGRAMSARBPROC gl_gen_programs; PFNGLDELETEPROGRAMSARBPROC gl_delete_programs; PFNGLBINDPROGRAMARBPROC gl_bind_program; PFNGLPROGRAMSTRINGARBPROC gl_program_string; PFNGLGETPROGRAMIVARBPROC gl_get_program_iv; PFNGLPROGRAMLOCALPARAMETER4FVARBPROC gl_program_local_parameter_4fv; PFNGLACTIVETEXTUREPROC gl_active_texture; PFNGLMULTITEXCOORD2FPROC gl_multi_tex_coord_2f; PFNGLVDPAUINITNVPROC gl_vdpau_init; PFNGLVDPAUFININVPROC gl_vdpau_fini; PFNGLVDPAUREGISTERVIDEOSURFACENVPROC gl_vdpau_register_video_surface; PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC gl_vdpau_register_output_surface; PFNGLVDPAUISSURFACENVPROC gl_vdpau_is_surface; PFNGLVDPAUUNREGISTERSURFACENVPROC gl_vdpau_unregister_surface; PFNGLVDPAUGETSURFACEIVNVPROC gl_vdpau_get_surface_iv; PFNGLVDPAUSURFACEACCESSNVPROC gl_vdpau_surface_access; PFNGLVDPAUMAPSURFACESNVPROC gl_vdpau_map_surfaces; PFNGLVDPAUUNMAPSURFACESNVPROC gl_vdpau_unmap_surfaces; unsigned int has_texture_non_power_of_two : 1; unsigned int has_texture_rectangle : 1; unsigned int has_texture_from_pixmap : 1; unsigned int has_framebuffer_object : 1; unsigned int has_fragment_program : 1; unsigned int has_multitexture : 1; unsigned int has_vdpau_interop : 1; }; GLVTable * gl_get_vtable(void) attribute_hidden; typedef struct _GLPixmapObject GLPixmapObject; struct _GLPixmapObject { Display *dpy; GLenum target; GLuint texture; unsigned int width; unsigned int height; Pixmap pixmap; GLXPixmap glx_pixmap; unsigned int is_bound : 1; }; GLPixmapObject * gl_create_pixmap_object( Display *dpy, GLenum target, unsigned int width, unsigned int height ) attribute_hidden; void gl_destroy_pixmap_object(GLPixmapObject *pixo) attribute_hidden; int gl_bind_pixmap_object(GLPixmapObject *pixo) attribute_hidden; int gl_unbind_pixmap_object(GLPixmapObject *pixo) attribute_hidden; typedef struct _GLFramebufferObject GLFramebufferObject; struct _GLFramebufferObject { unsigned int width; unsigned int height; GLuint fbo; GLuint old_fbo; unsigned int is_bound : 1; }; GLFramebufferObject * gl_create_framebuffer_object( GLenum target, GLuint texture, unsigned int width, unsigned int height ) attribute_hidden; void gl_destroy_framebuffer_object(GLFramebufferObject *fbo) attribute_hidden; int gl_bind_framebuffer_object(GLFramebufferObject *fbo) attribute_hidden; int gl_unbind_framebuffer_object(GLFramebufferObject *fbo) attribute_hidden; int gl_vdpau_init(VdpDevice device, VdpGetProcAddress get_proc_address) attribute_hidden; void gl_vdpau_exit(void) attribute_hidden; typedef struct _GLVdpSurface GLVdpSurface; struct _GLVdpSurface { GLvdpauSurfaceNV surface; GLenum target; unsigned int num_textures; GLuint textures[4]; unsigned int is_bound : 1; }; GLVdpSurface * gl_vdpau_create_video_surface(GLenum target, VdpVideoSurface surface) attribute_hidden; GLVdpSurface * gl_vdpau_create_output_surface(GLenum target, VdpOutputSurface surface) attribute_hidden; void gl_vdpau_destroy_surface(GLVdpSurface *s) attribute_hidden; int gl_vdpau_bind_surface(GLVdpSurface *s) attribute_hidden; int gl_vdpau_unbind_surface(GLVdpSurface *s) attribute_hidden; #endif /* UTILS_GLX_H */ vdpau-driver-0.7.4/src/utils_x11.c000066400000000000000000000037101203356434100167200ustar00rootroot00000000000000/* * utils_x11.h - X11 utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include #include "utils_x11.h" #include "utils.h" // X error trap static int x11_error_code = 0; static int (*old_error_handler)(Display *, XErrorEvent *); static int error_handler(Display *dpy, XErrorEvent *error) { x11_error_code = error->error_code; return 0; } void x11_trap_errors(void) { x11_error_code = 0; old_error_handler = XSetErrorHandler(error_handler); } int x11_untrap_errors(void) { XSetErrorHandler(old_error_handler); return x11_error_code; } int x11_get_geometry( Display *dpy, Drawable drawable, int *px, int *py, unsigned int *pwidth, unsigned int *pheight ) { Window rootwin; int x, y; unsigned int width, height, border_width, depth; x11_trap_errors(); XGetGeometry( dpy, drawable, &rootwin, &x, &y, &width, &height, &border_width, &depth ); if (x11_untrap_errors()) return 0; if (px) *px = x; if (py) *py = y; if (pwidth) *pwidth = width; if (pheight) *pheight = height; return 1; } vdpau-driver-0.7.4/src/utils_x11.h000066400000000000000000000023251203356434100167260ustar00rootroot00000000000000/* * utils_x11.h - X11 utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef UTILS_X11_H #define UTILS_X11_H #include "config.h" #include void x11_trap_errors(void) attribute_hidden; int x11_untrap_errors(void) attribute_hidden; int x11_get_geometry( Display *dpy, Drawable drawable, int *px, int *py, unsigned int *pwidth, unsigned int *pheight ) attribute_hidden; #endif /* UTILS_X11_H */ vdpau-driver-0.7.4/src/vaapi_compat.h000066400000000000000000000040131203356434100175340ustar00rootroot00000000000000/* * vaapi_compat.h - VA-API compatibility glue * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VAAPI_COMPAT_H #define VAAPI_COMPAT_H #ifndef VA_INVALID_ID #define VA_INVALID_ID 0xffffffff #endif #ifndef VA_INVALID_BUFFER #define VA_INVALID_BUFFER VA_INVALID_ID #endif #ifndef VA_INVALID_SURFACE #define VA_INVALID_SURFACE VA_INVALID_ID #endif #ifndef VA_STATUS_ERROR_UNIMPLEMENTED #define VA_STATUS_ERROR_UNIMPLEMENTED 0x00000014 #endif #ifndef VA_DISPLAY_X11 #define VA_DISPLAY_X11 1 #endif #ifndef VA_DISPLAY_GLX #define VA_DISPLAY_GLX 2 #endif #ifndef VA_FILTER_SCALING_DEFAULT #define VA_FILTER_SCALING_DEFAULT 0x00000000 #endif #ifndef VA_FILTER_SCALING_FAST #define VA_FILTER_SCALING_FAST 0x00000100 #endif #ifndef VA_FILTER_SCALING_HQ #define VA_FILTER_SCALING_HQ 0x00000200 #endif #ifndef VA_FILTER_SCALING_NL_ANAMORPHIC #define VA_FILTER_SCALING_NL_ANAMORPHIC 0x00000300 #endif #ifndef VA_FILTER_SCALING_MASK #define VA_FILTER_SCALING_MASK 0x00000f00 #endif #ifndef VA_SRC_SMPTE_240 #define VA_SRC_SMPTE_240 0x00000040 #endif #if VA_CHECK_VERSION(0,31,1) typedef void *VADrawable; #else typedef Drawable VADrawable; #endif #endif /* VAAPI_COMPAT_H */ vdpau-driver-0.7.4/src/vdpau_buffer.c000066400000000000000000000162701203356434100175440ustar00rootroot00000000000000/* * vdpau_buffer.c - VDPAU backend for VA-API (VA buffers) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_buffer.h" #include "vdpau_driver.h" #include "vdpau_video.h" #include "vdpau_dump.h" #include "utils.h" #define DEBUG 1 #include "debug.h" // Destroy dead VA buffers void destroy_dead_va_buffers( vdpau_driver_data_t *driver_data, object_context_p obj_context ) { object_buffer_p obj_buffer; unsigned int i; if (obj_context->dead_buffers_count < 1) return; ASSERT(obj_context->dead_buffers); for (i = 0; i < obj_context->dead_buffers_count; i++) { obj_buffer = VDPAU_BUFFER(obj_context->dead_buffers[i]); ASSERT(obj_buffer); destroy_va_buffer(driver_data, obj_buffer); } obj_context->dead_buffers_count = 0; } // Create VA buffer object object_buffer_p create_va_buffer( vdpau_driver_data_t *driver_data, VAContextID context, VABufferType buffer_type, unsigned int num_elements, unsigned int size ) { VABufferID buffer_id; object_buffer_p obj_buffer; buffer_id = object_heap_allocate(&driver_data->buffer_heap); if (buffer_id == VA_INVALID_BUFFER) return NULL; obj_buffer = VDPAU_BUFFER(buffer_id); if (!obj_buffer) return NULL; obj_buffer->va_context = context; obj_buffer->type = buffer_type; obj_buffer->max_num_elements = num_elements; obj_buffer->num_elements = num_elements; obj_buffer->buffer_size = size * num_elements; obj_buffer->buffer_data = malloc(obj_buffer->buffer_size); obj_buffer->mtime = 0; obj_buffer->delayed_destroy = 0; if (!obj_buffer->buffer_data) { destroy_va_buffer(driver_data, obj_buffer); return NULL; } return obj_buffer; } // Destroy VA buffer object void destroy_va_buffer( vdpau_driver_data_t *driver_data, object_buffer_p obj_buffer ) { if (!obj_buffer) return; if (obj_buffer->buffer_data) { free(obj_buffer->buffer_data); obj_buffer->buffer_data = NULL; } object_heap_free(&driver_data->buffer_heap, (object_base_p)obj_buffer); } // Schedule VA buffer object for destruction void schedule_destroy_va_buffer( vdpau_driver_data_p driver_data, object_buffer_p obj_buffer ) { object_context_p obj_context = VDPAU_CONTEXT(obj_buffer->va_context); if (!obj_context) return; realloc_buffer( (void **)&obj_context->dead_buffers, &obj_context->dead_buffers_count_max, 16 + obj_context->dead_buffers_count, sizeof(*obj_context->dead_buffers) ); ASSERT(obj_context->dead_buffers); obj_context->dead_buffers[obj_context->dead_buffers_count] = obj_buffer->base.id; obj_context->dead_buffers_count++; obj_buffer->delayed_destroy = 1; } // vaCreateBuffer VAStatus vdpau_CreateBuffer( VADriverContextP ctx, VAContextID context, VABufferType type, unsigned int size, unsigned int num_elements, void *data, VABufferID *buf_id ) { VDPAU_DRIVER_DATA_INIT; if (buf_id) *buf_id = VA_INVALID_BUFFER; /* Validate type */ switch (type) { case VAPictureParameterBufferType: case VAIQMatrixBufferType: case VASliceParameterBufferType: case VASliceDataBufferType: case VABitPlaneBufferType: case VAImageBufferType: /* Ok */ break; default: D(bug("ERROR: unsupported buffer type %d\n", type)); return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; } object_buffer_p obj_buffer; obj_buffer = create_va_buffer(driver_data, context, type, num_elements, size); if (!obj_buffer) return VA_STATUS_ERROR_ALLOCATION_FAILED; if (data) memcpy(obj_buffer->buffer_data, data, obj_buffer->buffer_size); if (buf_id) *buf_id = obj_buffer->base.id; return VA_STATUS_SUCCESS; } // vaDestroyBuffer VAStatus vdpau_DestroyBuffer( VADriverContextP ctx, VABufferID buffer_id ) { VDPAU_DRIVER_DATA_INIT; object_buffer_p obj_buffer = VDPAU_BUFFER(buffer_id); if (obj_buffer && !obj_buffer->delayed_destroy) destroy_va_buffer(driver_data, obj_buffer); return VA_STATUS_SUCCESS; } // vaBufferSetNumElements VAStatus vdpau_BufferSetNumElements( VADriverContextP ctx, VABufferID buf_id, unsigned int num_elements ) { VDPAU_DRIVER_DATA_INIT; object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; if (num_elements < 0 || num_elements > obj_buffer->max_num_elements) return VA_STATUS_ERROR_UNKNOWN; obj_buffer->num_elements = num_elements; return VA_STATUS_SUCCESS; } // vaMapBuffer VAStatus vdpau_MapBuffer( VADriverContextP ctx, VABufferID buf_id, void **pbuf ) { VDPAU_DRIVER_DATA_INIT; object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; if (pbuf) *pbuf = obj_buffer->buffer_data; if (obj_buffer->buffer_data == NULL) return VA_STATUS_ERROR_UNKNOWN; ++obj_buffer->mtime; return VA_STATUS_SUCCESS; } // vaUnmapBuffer VAStatus vdpau_UnmapBuffer( VADriverContextP ctx, VABufferID buf_id ) { VDPAU_DRIVER_DATA_INIT; object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; ++obj_buffer->mtime; return VA_STATUS_SUCCESS; } // vaBufferInfo VAStatus vdpau_BufferInfo_0_31_1( VADriverContextP ctx, VAContextID context, VABufferID buf_id, VABufferType *type, unsigned int *size, unsigned int *num_elements ) { return vdpau_BufferInfo(ctx, buf_id, type, size, num_elements); } VAStatus vdpau_BufferInfo( VADriverContextP ctx, VABufferID buf_id, VABufferType *type, unsigned int *size, unsigned int *num_elements ) { VDPAU_DRIVER_DATA_INIT; object_buffer_p obj_buffer = VDPAU_BUFFER(buf_id); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; if (type) *type = obj_buffer->type; if (size) *size = obj_buffer->buffer_size / obj_buffer->num_elements; if (num_elements) *num_elements = obj_buffer->num_elements; return VA_STATUS_SUCCESS; } vdpau-driver-0.7.4/src/vdpau_buffer.h000066400000000000000000000065601203356434100175520ustar00rootroot00000000000000/* * vdpau_buffer.h - VDPAU backend for VA-API (VA buffers) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_BUFFER_H #define VDPAU_BUFFER_H #include "vdpau_driver.h" typedef struct object_buffer object_buffer_t; struct object_buffer { struct object_base base; VAContextID va_context; VABufferType type; void *buffer_data; unsigned int buffer_size; unsigned int max_num_elements; unsigned int num_elements; uint64_t mtime; unsigned int delayed_destroy : 1; }; // Destroy dead VA buffers void destroy_dead_va_buffers( vdpau_driver_data_t *driver_data, object_context_p obj_context ) attribute_hidden; // Create VA buffer object object_buffer_p create_va_buffer( vdpau_driver_data_p driver_data, VAContextID context, VABufferType buffer_type, unsigned int num_elements, unsigned int size ) attribute_hidden; // Destroy VA buffer object void destroy_va_buffer( vdpau_driver_data_p driver_data, object_buffer_p obj_buffer ) attribute_hidden; // Schedule VA buffer object for destruction void schedule_destroy_va_buffer( vdpau_driver_data_p driver_data, object_buffer_p obj_buffer ) attribute_hidden; // vaCreateBuffer VAStatus vdpau_CreateBuffer( VADriverContextP ctx, VAContextID context, VABufferType type, unsigned int size, unsigned int num_elements, void *data, VABufferID *buf_id ) attribute_hidden; // vaDestroyBuffer VAStatus vdpau_DestroyBuffer( VADriverContextP ctx, VABufferID buffer_id ) attribute_hidden; // vaBufferSetNumElements VAStatus vdpau_BufferSetNumElements( VADriverContextP ctx, VABufferID buf_id, unsigned int num_elements ) attribute_hidden; // vaMapBuffer VAStatus vdpau_MapBuffer( VADriverContextP ctx, VABufferID buf_id, void **pbuf ) attribute_hidden; // vaUnmapBuffer VAStatus vdpau_UnmapBuffer( VADriverContextP ctx, VABufferID buf_id ) attribute_hidden; // vaBufferInfo VAStatus vdpau_BufferInfo_0_31_1( VADriverContextP ctx, VAContextID context, VABufferID buf_id, VABufferType *type, unsigned int *size, unsigned int *num_elements ) attribute_hidden; VAStatus vdpau_BufferInfo( VADriverContextP ctx, VABufferID buf_id, VABufferType *type, unsigned int *size, unsigned int *num_elements ) attribute_hidden; #endif /* VDPAU_BUFFER_H */ vdpau-driver-0.7.4/src/vdpau_decode.c000066400000000000000000001363671203356434100175300ustar00rootroot00000000000000/* * vdpau_decode.c - VDPAU backend for VA-API (decoder) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_decode.h" #include "vdpau_driver.h" #include "vdpau_buffer.h" #include "vdpau_video.h" #include "vdpau_dump.h" #include "utils.h" #include "put_bits.h" #define DEBUG 1 #include "debug.h" // Translates VdpDecoderProfile to VdpCodec VdpCodec get_VdpCodec(VdpDecoderProfile profile) { switch (profile) { case VDP_DECODER_PROFILE_MPEG1: return VDP_CODEC_MPEG1; case VDP_DECODER_PROFILE_MPEG2_SIMPLE: case VDP_DECODER_PROFILE_MPEG2_MAIN: return VDP_CODEC_MPEG2; #if USE_VDPAU_MPEG4 case VDP_DECODER_PROFILE_MPEG4_PART2_SP: case VDP_DECODER_PROFILE_MPEG4_PART2_ASP: case VDP_DECODER_PROFILE_DIVX4_QMOBILE: case VDP_DECODER_PROFILE_DIVX4_MOBILE: case VDP_DECODER_PROFILE_DIVX4_HOME_THEATER: case VDP_DECODER_PROFILE_DIVX4_HD_1080P: case VDP_DECODER_PROFILE_DIVX5_QMOBILE: case VDP_DECODER_PROFILE_DIVX5_MOBILE: case VDP_DECODER_PROFILE_DIVX5_HOME_THEATER: case VDP_DECODER_PROFILE_DIVX5_HD_1080P: return VDP_CODEC_MPEG4; #endif case VDP_DECODER_PROFILE_H264_BASELINE: case VDP_DECODER_PROFILE_H264_MAIN: case VDP_DECODER_PROFILE_H264_HIGH: return VDP_CODEC_H264; case VDP_DECODER_PROFILE_VC1_SIMPLE: case VDP_DECODER_PROFILE_VC1_MAIN: case VDP_DECODER_PROFILE_VC1_ADVANCED: return VDP_CODEC_VC1; } return 0; } // Translates VAProfile to VdpDecoderProfile VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile) { switch (profile) { case VAProfileMPEG2Simple: return VDP_DECODER_PROFILE_MPEG2_SIMPLE; case VAProfileMPEG2Main: return VDP_DECODER_PROFILE_MPEG2_MAIN; #if USE_VDPAU_MPEG4 case VAProfileMPEG4Simple: return VDP_DECODER_PROFILE_MPEG4_PART2_SP; case VAProfileMPEG4AdvancedSimple: return VDP_DECODER_PROFILE_MPEG4_PART2_ASP; #endif case VAProfileH264Baseline: return VDP_DECODER_PROFILE_H264_BASELINE; case VAProfileH264Main: return VDP_DECODER_PROFILE_H264_MAIN; case VAProfileH264High: return VDP_DECODER_PROFILE_H264_HIGH; case VAProfileVC1Simple: return VDP_DECODER_PROFILE_VC1_SIMPLE; case VAProfileVC1Main: return VDP_DECODER_PROFILE_VC1_MAIN; case VAProfileVC1Advanced: return VDP_DECODER_PROFILE_VC1_ADVANCED; default: break; } return (VdpDecoderProfile)-1; } // Checks whether the VDPAU implementation supports the specified profile static inline VdpBool is_supported_profile( vdpau_driver_data_t *driver_data, VdpDecoderProfile profile ) { VdpBool is_supported = VDP_FALSE; VdpStatus vdp_status; uint32_t max_level, max_references, max_width, max_height; if (profile == (VdpDecoderProfile)-1) return VDP_FALSE; vdp_status = vdpau_decoder_query_capabilities( driver_data, driver_data->vdp_device, profile, &is_supported, &max_level, &max_references, &max_width, &max_height ); return (VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()") && is_supported); } // Checks decoder for profile/entrypoint is available VAStatus check_decoder( vdpau_driver_data_t *driver_data, VAProfile profile, VAEntrypoint entrypoint ) { if (!is_supported_profile(driver_data, get_VdpDecoderProfile(profile))) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; /* VDPAU only supports VLD */ if (entrypoint != VAEntrypointVLD) return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; return VA_STATUS_SUCCESS; } // Computes value for VdpDecoderCreate()::max_references parameter static int get_max_ref_frames( VdpDecoderProfile profile, unsigned int width, unsigned int height ) { int max_ref_frames = 2; switch (profile) { case VDP_DECODER_PROFILE_H264_MAIN: case VDP_DECODER_PROFILE_H264_HIGH: { /* level 4.1 limits */ unsigned int aligned_width = (width + 15) & -16; unsigned int aligned_height = (height + 15) & -16; unsigned int surface_size = (aligned_width * aligned_height * 3) / 2; if ((max_ref_frames = (12 * 1024 * 1024) / surface_size) > 16) max_ref_frames = 16; break; } } return max_ref_frames; } // Returns the maximum number of reference frames of a decode session static inline int get_num_ref_frames(object_context_p obj_context) { if (obj_context->vdp_codec == VDP_CODEC_H264) return obj_context->vdp_picture_info.h264.num_ref_frames; return 2; } // Ensure VDPAU decoder is created for the specified number of reference frames static VdpStatus ensure_decoder_with_max_refs( vdpau_driver_data_t *driver_data, object_context_p obj_context, int max_ref_frames ) { VdpStatus vdp_status; if (max_ref_frames < 0) max_ref_frames = get_max_ref_frames(obj_context->vdp_profile, obj_context->picture_width, obj_context->picture_height); if (obj_context->vdp_decoder == VDP_INVALID_HANDLE || obj_context->max_ref_frames < max_ref_frames) { obj_context->max_ref_frames = max_ref_frames; if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) { vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder); obj_context->vdp_decoder = VDP_INVALID_HANDLE; } vdp_status = vdpau_decoder_create( driver_data, driver_data->vdp_device, obj_context->vdp_profile, obj_context->picture_width, obj_context->picture_height, max_ref_frames, &obj_context->vdp_decoder ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderCreate()")) return vdp_status; } return VDP_STATUS_OK; } // Lazy allocate (generated) slice data buffer. Buffer lives until vaDestroyContext() static uint8_t * alloc_gen_slice_data(object_context_p obj_context, unsigned int size) { uint8_t *gen_slice_data = obj_context->gen_slice_data; if (obj_context->gen_slice_data_size + size > obj_context->gen_slice_data_size_max) { obj_context->gen_slice_data_size_max += size; gen_slice_data = realloc(obj_context->gen_slice_data, obj_context->gen_slice_data_size_max); if (!gen_slice_data) return NULL; obj_context->gen_slice_data = gen_slice_data; } gen_slice_data += obj_context->gen_slice_data_size; obj_context->gen_slice_data_size += size; return gen_slice_data; } // Lazy allocate VdpBitstreamBuffer. Buffer lives until vaDestroyContext() static VdpBitstreamBuffer * alloc_VdpBitstreamBuffer(object_context_p obj_context) { VdpBitstreamBuffer *vdp_bitstream_buffers; vdp_bitstream_buffers = realloc_buffer( (void **)&obj_context->vdp_bitstream_buffers, &obj_context->vdp_bitstream_buffers_count_max, 1 + obj_context->vdp_bitstream_buffers_count, sizeof(*obj_context->vdp_bitstream_buffers) ); if (!vdp_bitstream_buffers) return NULL; return &vdp_bitstream_buffers[obj_context->vdp_bitstream_buffers_count++]; } // Append VASliceDataBuffer hunk into VDPAU buffer static int append_VdpBitstreamBuffer( object_context_p obj_context, const uint8_t *buffer, uint32_t buffer_size ) { VdpBitstreamBuffer *bitstream_buffer; bitstream_buffer = alloc_VdpBitstreamBuffer(obj_context); if (!bitstream_buffer) return -1; bitstream_buffer->struct_version = VDP_BITSTREAM_BUFFER_VERSION; bitstream_buffer->bitstream = buffer; bitstream_buffer->bitstream_bytes = buffer_size; return 0; } // Initialize VdpReferenceFrameH264 to default values static void init_VdpReferenceFrameH264(VdpReferenceFrameH264 *rf) { rf->surface = VDP_INVALID_HANDLE; rf->is_long_term = VDP_FALSE; rf->top_is_reference = VDP_FALSE; rf->bottom_is_reference = VDP_FALSE; rf->field_order_cnt[0] = 0; rf->field_order_cnt[1] = 0; rf->frame_idx = 0; } static const uint8_t ff_identity[64] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }; static const uint8_t ff_zigzag_direct[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; static const uint8_t ff_mpeg1_default_intra_matrix[64] = { 8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37, 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40, 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58, 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83 }; static const uint8_t ff_mpeg1_default_non_intra_matrix[64] = { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; static const uint8_t ff_mpeg4_default_intra_matrix[64] = { 8, 17, 18, 19, 21, 23, 25, 27, 17, 18, 19, 21, 23, 25, 27, 28, 20, 21, 22, 23, 24, 26, 28, 30, 21, 22, 23, 24, 26, 28, 30, 32, 22, 23, 24, 26, 28, 30, 32, 35, 23, 24, 26, 28, 30, 32, 35, 38, 25, 26, 28, 30, 32, 35, 38, 41, 27, 28, 30, 32, 35, 38, 41, 45, }; static const uint8_t ff_mpeg4_default_non_intra_matrix[64] = { 16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24, 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27, 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30, 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33, }; // Compute integer log2 static inline int ilog2(uint32_t v) { /* From */ uint32_t r, shift; r = (v > 0xffff) << 4; v >>= r; shift = (v > 0xff ) << 3; v >>= shift; r |= shift; shift = (v > 0xf ) << 2; v >>= shift; r |= shift; shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; return r | (v >> 1); } // Translate VASurfaceID static int translate_VASurfaceID( vdpau_driver_data_t *driver_data, VASurfaceID va_surface, VdpVideoSurface *vdp_surface ) { object_surface_p obj_surface; if (va_surface == VA_INVALID_SURFACE) { *vdp_surface = VDP_INVALID_HANDLE; return 1; } obj_surface = VDPAU_SURFACE(va_surface); if (!obj_surface) return 0; *vdp_surface = obj_surface->vdp_surface; return 1; } // Translate VAPictureH264 static int translate_VAPictureH264( vdpau_driver_data_t *driver_data, const VAPictureH264 *va_pic, VdpReferenceFrameH264 *rf ) { // Handle invalid surfaces specifically if (va_pic->picture_id == VA_INVALID_SURFACE) { init_VdpReferenceFrameH264(rf); return 1; } if (!translate_VASurfaceID(driver_data, va_pic->picture_id, &rf->surface)) return 0; rf->is_long_term = (va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE) != 0; if ((va_pic->flags & (VA_PICTURE_H264_TOP_FIELD|VA_PICTURE_H264_BOTTOM_FIELD)) == 0) { rf->top_is_reference = VDP_TRUE; rf->bottom_is_reference = VDP_TRUE; } else { rf->top_is_reference = (va_pic->flags & VA_PICTURE_H264_TOP_FIELD) != 0; rf->bottom_is_reference = (va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; } rf->field_order_cnt[0] = va_pic->TopFieldOrderCnt; rf->field_order_cnt[1] = va_pic->BottomFieldOrderCnt; rf->frame_idx = va_pic->frame_idx; return 1; } // Translate no buffer static int translate_nothing( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { return 1; } static int translate_VASliceDataBuffer_MPEG2( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; VASliceParameterBufferMPEG2 * const slice_params = obj_context->last_slice_params; uint8_t *slice_header; unsigned int i; /* Check we have the start code */ for (i = 0; i < obj_context->last_slice_params_count; i++) { VASliceParameterBufferMPEG2 * const slice_param = &slice_params[i]; uint8_t * const buf = (uint8_t *)obj_buffer->buffer_data + slice_param->slice_data_offset; if (memcmp(buf, start_code_prefix, sizeof(start_code_prefix)) != 0) { if (append_VdpBitstreamBuffer(obj_context, start_code_prefix, sizeof(start_code_prefix)) < 0) return 0; slice_header = alloc_gen_slice_data(obj_context, 1); if (!slice_header) return 0; slice_header[0] = slice_param->slice_vertical_position + 1; if (append_VdpBitstreamBuffer(obj_context, slice_header, 1) < 0) return 0; } if (append_VdpBitstreamBuffer(obj_context, buf, slice_param->slice_data_size) < 0) return 0; } return 1; } // Translate VASliceDataBuffer static int translate_VASliceDataBuffer( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { if (obj_context->vdp_codec == VDP_CODEC_H264) { /* Check we have the start code */ /* XXX: check for other codecs too? */ /* XXX: this assumes we get SliceParams before SliceData */ static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; VASliceParameterBufferH264 * const slice_params = obj_context->last_slice_params; unsigned int i; for (i = 0; i < obj_context->last_slice_params_count; i++) { VASliceParameterBufferH264 * const slice_param = &slice_params[i]; uint8_t *buf = (uint8_t *)obj_buffer->buffer_data + slice_param->slice_data_offset; if (memcmp(buf, start_code_prefix, sizeof(start_code_prefix)) != 0) { if (append_VdpBitstreamBuffer(obj_context, start_code_prefix, sizeof(start_code_prefix)) < 0) return 0; } if (append_VdpBitstreamBuffer(obj_context, buf, slice_param->slice_data_size) < 0) return 0; } return 1; } if (obj_context->vdp_codec == VDP_CODEC_MPEG2) return translate_VASliceDataBuffer_MPEG2(driver_data, obj_context, obj_buffer); #if USE_VDPAU_MPEG4 if (obj_context->vdp_codec == VDP_CODEC_MPEG4 && obj_context->vdp_bitstream_buffers_count == 0) { PutBitContext pb; uint8_t slice_header_buffer[32]; uint8_t *slice_header; int slice_header_size; const uint8_t *slice_data = obj_buffer->buffer_data; uint32_t slice_data_size = obj_buffer->buffer_size; VAPictureParameterBufferMPEG4 * const pic_param = obj_context->last_pic_param; VASliceParameterBufferMPEG4 * const slice_param = obj_context->last_slice_params; int time_incr = 1 + ilog2(pic_param->vop_time_increment_resolution - 1); if (time_incr < 1) time_incr = 1; static const uint16_t VOP_STARTCODE = 0x01b6; enum { VOP_I_TYPE = 0, VOP_P_TYPE, VOP_B_TYPE, VOP_S_TYPE }; /* XXX: this is a hack to compute the length of modulo_time_base "1" sequence. We probably should be reconstructing through an extra VOP field in VA-API? */ int nbits = (32 + /* VOP start code */ 2 + /* vop_coding_type */ 1 + /* modulo_time_base "0" */ 1 + /* marker_bit */ time_incr + /* vop_time_increment */ 1 + /* marker_bit */ 1 + /* vop_coded */ (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE ? 1 : 0) + 3 + /* intra_dc_vlc_thr */ (pic_param->vol_fields.bits.interlaced ? 2 : 0) + 5 + /* vop_quant */ (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE ? 3 : 0) + (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE ? 3 : 0)); if ((nbits = slice_param->macroblock_offset - (nbits % 8)) < 0) nbits += 8; /* Reconstruct the VOP header */ init_put_bits(&pb, slice_header_buffer, sizeof(slice_header_buffer)); put_bits(&pb, 16, 0); /* vop header */ put_bits(&pb, 16, VOP_STARTCODE); /* vop header */ put_bits(&pb, 2, pic_param->vop_fields.bits.vop_coding_type); while (nbits-- > 0) put_bits(&pb, 1, 1); /* modulo_time_base "1" */ put_bits(&pb, 1, 0); /* modulo_time_base "0" */ put_bits(&pb, 1, 1); /* marker */ put_bits(&pb, time_incr, 0); /* time increment */ put_bits(&pb, 1, 1); /* marker */ put_bits(&pb, 1, 1); /* vop coded */ if (pic_param->vop_fields.bits.vop_coding_type == VOP_P_TYPE) put_bits(&pb, 1, pic_param->vop_fields.bits.vop_rounding_type); put_bits(&pb, 3, pic_param->vop_fields.bits.intra_dc_vlc_thr); if (pic_param->vol_fields.bits.interlaced) { put_bits(&pb, 1, pic_param->vop_fields.bits.top_field_first); put_bits(&pb, 1, pic_param->vop_fields.bits.alternate_vertical_scan_flag); } put_bits(&pb, 5, slice_param->quant_scale); if (pic_param->vop_fields.bits.vop_coding_type != VOP_I_TYPE) put_bits(&pb, 3, pic_param->vop_fcode_forward); if (pic_param->vop_fields.bits.vop_coding_type == VOP_B_TYPE) put_bits(&pb, 3, pic_param->vop_fcode_backward); /* Merge in bits from the first byte of the slice */ ASSERT((put_bits_count(&pb) % 8) == slice_param->macroblock_offset); if ((put_bits_count(&pb) % 8) != slice_param->macroblock_offset) return 0; const int r = 8 - (put_bits_count(&pb) % 8); if (r > 0) put_bits(&pb, r, slice_data[0] & ((1U << r) - 1)); flush_put_bits(&pb); ASSERT((put_bits_count(&pb) % 8) == 0); slice_header_size = put_bits_count(&pb) / 8; ASSERT(slice_header_size <= sizeof(slice_header_buffer)); slice_header = alloc_gen_slice_data(obj_context, slice_header_size); if (!slice_header) return 0; memcpy(slice_header, slice_header_buffer, slice_header_size); if (append_VdpBitstreamBuffer(obj_context, slice_header, slice_header_size) < 0) return 0; if (append_VdpBitstreamBuffer(obj_context, slice_data + 1, slice_data_size - 1) < 0) return 0; return 1; } #endif if (append_VdpBitstreamBuffer(obj_context, obj_buffer->buffer_data, obj_buffer->buffer_size) < 0) return 0; return 1; } // Translate VAPictureParameterBufferMPEG2 static int translate_VAPictureParameterBufferMPEG2( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; VAPictureParameterBufferMPEG2 * const pic_param = obj_buffer->buffer_data; if (!translate_VASurfaceID(driver_data, pic_param->forward_reference_picture, &pic_info->forward_reference)) return 0; if (!translate_VASurfaceID(driver_data, pic_param->backward_reference_picture, &pic_info->backward_reference)) return 0; pic_info->picture_structure = pic_param->picture_coding_extension.bits.picture_structure; pic_info->picture_coding_type = pic_param->picture_coding_type; pic_info->intra_dc_precision = pic_param->picture_coding_extension.bits.intra_dc_precision; pic_info->frame_pred_frame_dct = pic_param->picture_coding_extension.bits.frame_pred_frame_dct; pic_info->concealment_motion_vectors = pic_param->picture_coding_extension.bits.concealment_motion_vectors; pic_info->intra_vlc_format = pic_param->picture_coding_extension.bits.intra_vlc_format; pic_info->alternate_scan = pic_param->picture_coding_extension.bits.alternate_scan; pic_info->q_scale_type = pic_param->picture_coding_extension.bits.q_scale_type; pic_info->top_field_first = pic_param->picture_coding_extension.bits.top_field_first; pic_info->full_pel_forward_vector = 0; pic_info->full_pel_backward_vector = 0; pic_info->f_code[0][0] = (pic_param->f_code >> 12) & 0xf; pic_info->f_code[0][1] = (pic_param->f_code >> 8) & 0xf; pic_info->f_code[1][0] = (pic_param->f_code >> 4) & 0xf; pic_info->f_code[1][1] = pic_param->f_code & 0xf; return 1; } // Translate VAIQMatrixBufferMPEG2 static int translate_VAIQMatrixBufferMPEG2( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; VAIQMatrixBufferMPEG2 * const iq_matrix = obj_buffer->buffer_data; const uint8_t *intra_matrix; const uint8_t *intra_matrix_lookup; const uint8_t *inter_matrix; const uint8_t *inter_matrix_lookup; int i; if (iq_matrix->load_intra_quantiser_matrix) { intra_matrix = iq_matrix->intra_quantiser_matrix; intra_matrix_lookup = ff_zigzag_direct; } else { intra_matrix = ff_mpeg1_default_intra_matrix; intra_matrix_lookup = ff_identity; } if (iq_matrix->load_non_intra_quantiser_matrix) { inter_matrix = iq_matrix->non_intra_quantiser_matrix; inter_matrix_lookup = ff_zigzag_direct; } else { inter_matrix = ff_mpeg1_default_non_intra_matrix; inter_matrix_lookup = ff_identity; } for (i = 0; i < 64; i++) { pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] = intra_matrix[i]; pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] = inter_matrix[i]; } return 1; } // Translate VASliceParameterBufferMPEG2 static int translate_VASliceParameterBufferMPEG2( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoMPEG1Or2 * const pic_info = &obj_context->vdp_picture_info.mpeg2; pic_info->slice_count += obj_buffer->num_elements; obj_context->last_slice_params = obj_buffer->buffer_data; obj_context->last_slice_params_count = obj_buffer->num_elements; return 1; } #if USE_VDPAU_MPEG4 // Translate VAPictureParameterBufferMPEG4 static int translate_VAPictureParameterBufferMPEG4( vdpau_driver_data_p driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4; VAPictureParameterBufferMPEG4 * const pic_param = obj_buffer->buffer_data; /* XXX: we don't support short-video-header formats */ if (pic_param->vol_fields.bits.short_video_header) return 0; if (!translate_VASurfaceID(driver_data, pic_param->forward_reference_picture, &pic_info->forward_reference)) return 0; if (!translate_VASurfaceID(driver_data, pic_param->backward_reference_picture, &pic_info->backward_reference)) return 0; if (pic_param->vol_fields.bits.interlaced) { vdpau_information_message("unsupported MPEG-4 video with interlaced " "content, please report this video\n"); pic_info->trd[0] = 2*pic_param->TRD; /* XXX: + d(0) */ pic_info->trb[0] = 2*pic_param->TRB; /* XXX: + d(0) */ pic_info->trd[1] = 2*pic_param->TRD; /* XXX: + d(1) */ pic_info->trb[1] = 2*pic_param->TRB; /* XXX: + d(1) */ } else { pic_info->trd[0] = pic_param->TRD; pic_info->trb[0] = pic_param->TRB; pic_info->trd[1] = 0; pic_info->trb[1] = 0; } pic_info->vop_time_increment_resolution = pic_param->vop_time_increment_resolution; pic_info->vop_coding_type = pic_param->vop_fields.bits.vop_coding_type; pic_info->vop_fcode_forward = pic_param->vop_fcode_forward; pic_info->vop_fcode_backward = pic_param->vop_fcode_backward; pic_info->resync_marker_disable = pic_param->vol_fields.bits.resync_marker_disable; pic_info->interlaced = pic_param->vol_fields.bits.interlaced; pic_info->quant_type = pic_param->vol_fields.bits.quant_type; pic_info->quarter_sample = pic_param->vol_fields.bits.quarter_sample; pic_info->short_video_header = pic_param->vol_fields.bits.short_video_header; pic_info->rounding_control = pic_param->vop_fields.bits.vop_rounding_type; pic_info->alternate_vertical_scan_flag = pic_param->vop_fields.bits.alternate_vertical_scan_flag; pic_info->top_field_first = pic_param->vop_fields.bits.top_field_first; obj_context->last_pic_param = obj_buffer->buffer_data; return 1; } // Translate VAIQMatrixBufferMPEG4 static int translate_VAIQMatrixBufferMPEG4( vdpau_driver_data_p driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoMPEG4Part2 * const pic_info = &obj_context->vdp_picture_info.mpeg4; VAIQMatrixBufferMPEG4 * const iq_matrix = obj_buffer->buffer_data; const uint8_t *intra_matrix; const uint8_t *intra_matrix_lookup; const uint8_t *inter_matrix; const uint8_t *inter_matrix_lookup; int i; if (iq_matrix->load_intra_quant_mat) { intra_matrix = iq_matrix->intra_quant_mat; intra_matrix_lookup = ff_zigzag_direct; } else { intra_matrix = ff_mpeg4_default_intra_matrix; intra_matrix_lookup = ff_identity; } if (iq_matrix->load_non_intra_quant_mat) { inter_matrix = iq_matrix->non_intra_quant_mat; inter_matrix_lookup = ff_zigzag_direct; } else { inter_matrix = ff_mpeg4_default_non_intra_matrix; inter_matrix_lookup = ff_identity; } for (i = 0; i < 64; i++) { pic_info->intra_quantizer_matrix[intra_matrix_lookup[i]] = intra_matrix[i]; pic_info->non_intra_quantizer_matrix[inter_matrix_lookup[i]] = inter_matrix[i]; } return 1; } // Translate VASliceParameterBufferMPEG4 static int translate_VASliceParameterBufferMPEG4( vdpau_driver_data_p driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { obj_context->last_slice_params = obj_buffer->buffer_data; obj_context->last_slice_params_count = obj_buffer->num_elements; return 1; } #endif // Translate VAPictureParameterBufferH264 static int translate_VAPictureParameterBufferH264( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; VAPictureParameterBufferH264 * const pic_param = obj_buffer->buffer_data; VAPictureH264 * const CurrPic = &pic_param->CurrPic; unsigned int i; pic_info->field_order_cnt[0] = CurrPic->TopFieldOrderCnt; pic_info->field_order_cnt[1] = CurrPic->BottomFieldOrderCnt; pic_info->is_reference = pic_param->pic_fields.bits.reference_pic_flag; pic_info->frame_num = pic_param->frame_num; pic_info->field_pic_flag = pic_param->pic_fields.bits.field_pic_flag; pic_info->bottom_field_flag = pic_param->pic_fields.bits.field_pic_flag && (CurrPic->flags & VA_PICTURE_H264_BOTTOM_FIELD) != 0; pic_info->num_ref_frames = pic_param->num_ref_frames; pic_info->mb_adaptive_frame_field_flag = pic_param->seq_fields.bits.mb_adaptive_frame_field_flag && !pic_info->field_pic_flag; pic_info->constrained_intra_pred_flag = pic_param->pic_fields.bits.constrained_intra_pred_flag; pic_info->weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag; pic_info->weighted_bipred_idc = pic_param->pic_fields.bits.weighted_bipred_idc; pic_info->frame_mbs_only_flag = pic_param->seq_fields.bits.frame_mbs_only_flag; pic_info->transform_8x8_mode_flag = pic_param->pic_fields.bits.transform_8x8_mode_flag; pic_info->chroma_qp_index_offset = pic_param->chroma_qp_index_offset; pic_info->second_chroma_qp_index_offset = pic_param->second_chroma_qp_index_offset; pic_info->pic_init_qp_minus26 = pic_param->pic_init_qp_minus26; pic_info->log2_max_frame_num_minus4 = pic_param->seq_fields.bits.log2_max_frame_num_minus4; pic_info->pic_order_cnt_type = pic_param->seq_fields.bits.pic_order_cnt_type; pic_info->log2_max_pic_order_cnt_lsb_minus4 = pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4; pic_info->delta_pic_order_always_zero_flag = pic_param->seq_fields.bits.delta_pic_order_always_zero_flag; pic_info->direct_8x8_inference_flag = pic_param->seq_fields.bits.direct_8x8_inference_flag; pic_info->entropy_coding_mode_flag = pic_param->pic_fields.bits.entropy_coding_mode_flag; pic_info->pic_order_present_flag = pic_param->pic_fields.bits.pic_order_present_flag; pic_info->deblocking_filter_control_present_flag = pic_param->pic_fields.bits.deblocking_filter_control_present_flag; pic_info->redundant_pic_cnt_present_flag = pic_param->pic_fields.bits.redundant_pic_cnt_present_flag; for (i = 0; i < 16; i++) { if (!translate_VAPictureH264(driver_data, &pic_param->ReferenceFrames[i], &pic_info->referenceFrames[i])) return 0; } return 1; } // Translate VAIQMatrixBufferH264 static int translate_VAIQMatrixBufferH264( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; VAIQMatrixBufferH264 * const iq_matrix = obj_buffer->buffer_data; int i, j; if (sizeof(pic_info->scaling_lists_4x4) == sizeof(iq_matrix->ScalingList4x4)) memcpy(pic_info->scaling_lists_4x4, iq_matrix->ScalingList4x4, sizeof(pic_info->scaling_lists_4x4)); else { for (j = 0; j < 6; j++) { for (i = 0; i < 16; i++) pic_info->scaling_lists_4x4[j][i] = iq_matrix->ScalingList4x4[j][i]; } } if (sizeof(pic_info->scaling_lists_8x8) == sizeof(iq_matrix->ScalingList8x8)) memcpy(pic_info->scaling_lists_8x8, iq_matrix->ScalingList8x8, sizeof(pic_info->scaling_lists_8x8)); else { for (j = 0; j < 2; j++) { for (i = 0; i < 64; i++) pic_info->scaling_lists_8x8[j][i] = iq_matrix->ScalingList8x8[j][i]; } } return 1; } // Translate VASliceParameterBufferH264 static int translate_VASliceParameterBufferH264( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoH264 * const pic_info = &obj_context->vdp_picture_info.h264; VASliceParameterBufferH264 * const slice_params = obj_buffer->buffer_data; VASliceParameterBufferH264 * const slice_param = &slice_params[obj_buffer->num_elements - 1]; pic_info->slice_count += obj_buffer->num_elements; pic_info->num_ref_idx_l0_active_minus1 = slice_param->num_ref_idx_l0_active_minus1; pic_info->num_ref_idx_l1_active_minus1 = slice_param->num_ref_idx_l1_active_minus1; obj_context->last_slice_params = obj_buffer->buffer_data; obj_context->last_slice_params_count = obj_buffer->num_elements; return 1; } // Translate VAPictureParameterBufferVC1 static int translate_VAPictureParameterBufferVC1( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1; VAPictureParameterBufferVC1 * const pic_param = obj_buffer->buffer_data; int picture_type, major_version, minor_version; if (!translate_VASurfaceID(driver_data, pic_param->forward_reference_picture, &pic_info->forward_reference)) return 0; if (!translate_VASurfaceID(driver_data, pic_param->backward_reference_picture, &pic_info->backward_reference)) return 0; switch (pic_param->picture_fields.bits.picture_type) { case 0: picture_type = 0; break; /* I */ case 1: picture_type = 1; break; /* P */ case 2: picture_type = 3; break; /* B */ case 3: picture_type = 4; break; /* BI */ case 4: picture_type = 1; break; /* P "skipped" */ default: return 0; } pic_info->picture_type = picture_type; pic_info->frame_coding_mode = pic_param->picture_fields.bits.frame_coding_mode; pic_info->postprocflag = pic_param->post_processing != 0; pic_info->pulldown = pic_param->sequence_fields.bits.pulldown; pic_info->interlace = pic_param->sequence_fields.bits.interlace; pic_info->tfcntrflag = pic_param->sequence_fields.bits.tfcntrflag; pic_info->finterpflag = pic_param->sequence_fields.bits.finterpflag; pic_info->psf = pic_param->sequence_fields.bits.psf; pic_info->dquant = pic_param->pic_quantizer_fields.bits.dquant; pic_info->panscan_flag = pic_param->entrypoint_fields.bits.panscan_flag; pic_info->refdist_flag = pic_param->reference_fields.bits.reference_distance_flag; pic_info->quantizer = pic_param->pic_quantizer_fields.bits.quantizer; pic_info->extended_mv = pic_param->mv_fields.bits.extended_mv_flag; pic_info->extended_dmv = pic_param->mv_fields.bits.extended_dmv_flag; pic_info->overlap = pic_param->sequence_fields.bits.overlap; pic_info->vstransform = pic_param->transform_fields.bits.variable_sized_transform_flag; pic_info->loopfilter = pic_param->entrypoint_fields.bits.loopfilter; pic_info->fastuvmc = pic_param->fast_uvmc_flag; pic_info->range_mapy_flag = pic_param->range_mapping_fields.bits.luma_flag; pic_info->range_mapy = pic_param->range_mapping_fields.bits.luma; pic_info->range_mapuv_flag = pic_param->range_mapping_fields.bits.chroma_flag; pic_info->range_mapuv = pic_param->range_mapping_fields.bits.chroma; pic_info->multires = pic_param->sequence_fields.bits.multires; pic_info->syncmarker = pic_param->sequence_fields.bits.syncmarker; pic_info->rangered = pic_param->sequence_fields.bits.rangered; if (!vdpau_is_nvidia(driver_data, &major_version, &minor_version) || (major_version > 180 || minor_version >= 35)) pic_info->rangered |= pic_param->range_reduction_frame << 1; pic_info->maxbframes = pic_param->sequence_fields.bits.max_b_frames; pic_info->deblockEnable = pic_param->post_processing != 0; /* XXX: this is NVIDIA's vdpau.c semantics (postprocflag & 1) */ pic_info->pquant = pic_param->pic_quantizer_fields.bits.pic_quantizer_scale; return 1; } // Translate VASliceParameterBufferVC1 static int translate_VASliceParameterBufferVC1( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { VdpPictureInfoVC1 * const pic_info = &obj_context->vdp_picture_info.vc1; pic_info->slice_count += obj_buffer->num_elements; obj_context->last_slice_params = obj_buffer->buffer_data; obj_context->last_slice_params_count = obj_buffer->num_elements; return 1; } // Translate VA buffer typedef int (*translate_buffer_func_t)(vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer); typedef struct translate_buffer_info translate_buffer_info_t; struct translate_buffer_info { VdpCodec codec; VABufferType type; translate_buffer_func_t func; }; static int translate_buffer( vdpau_driver_data_t *driver_data, object_context_p obj_context, object_buffer_p obj_buffer ) { static const translate_buffer_info_t translate_info[] = { #define _(CODEC, TYPE) \ { VDP_CODEC_##CODEC, VA##TYPE##BufferType, \ translate_VA##TYPE##Buffer##CODEC } _(MPEG2, PictureParameter), _(MPEG2, IQMatrix), _(MPEG2, SliceParameter), #if USE_VDPAU_MPEG4 _(MPEG4, PictureParameter), _(MPEG4, IQMatrix), _(MPEG4, SliceParameter), #endif _(H264, PictureParameter), _(H264, IQMatrix), _(H264, SliceParameter), _(VC1, PictureParameter), _(VC1, SliceParameter), #undef _ { VDP_CODEC_VC1, VABitPlaneBufferType, translate_nothing }, { 0, VASliceDataBufferType, translate_VASliceDataBuffer }, { 0, 0, NULL } }; const translate_buffer_info_t *tbip; for (tbip = translate_info; tbip->func != NULL; tbip++) { if (tbip->codec && tbip->codec != obj_context->vdp_codec) continue; if (tbip->type != obj_buffer->type) continue; return tbip->func(driver_data, obj_context, obj_buffer); } D(bug("ERROR: no translate function found for %s%s\n", string_of_VABufferType(obj_buffer->type), obj_context->vdp_codec ? string_of_VdpCodec(obj_context->vdp_codec) : NULL)); return 0; } // vaQueryConfigProfiles VAStatus vdpau_QueryConfigProfiles( VADriverContextP ctx, VAProfile *profile_list, int *num_profiles ) { VDPAU_DRIVER_DATA_INIT; static const VAProfile va_profiles[] = { VAProfileMPEG2Simple, VAProfileMPEG2Main, VAProfileMPEG4Simple, VAProfileMPEG4AdvancedSimple, VAProfileMPEG4Main, VAProfileH264Baseline, VAProfileH264Main, VAProfileH264High, VAProfileVC1Simple, VAProfileVC1Main, VAProfileVC1Advanced }; int i, n = 0; for (i = 0; i < ARRAY_ELEMS(va_profiles); i++) { VAProfile profile = va_profiles[i]; VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile); if (is_supported_profile(driver_data, vdp_profile)) profile_list[n++] = profile; } /* If the assert fails then VDPAU_MAX_PROFILES needs to be bigger */ ASSERT(n <= VDPAU_MAX_PROFILES); if (num_profiles) *num_profiles = n; return VA_STATUS_SUCCESS; } // vaQueryConfigEntrypoints VAStatus vdpau_QueryConfigEntrypoints( VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints ) { VDPAU_DRIVER_DATA_INIT; VdpDecoderProfile vdp_profile = get_VdpDecoderProfile(profile); if (!is_supported_profile(driver_data, vdp_profile)) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; VAEntrypoint entrypoint; switch (profile) { case VAProfileMPEG2Simple: case VAProfileMPEG2Main: entrypoint = VAEntrypointVLD; break; case VAProfileMPEG4Simple: case VAProfileMPEG4AdvancedSimple: case VAProfileMPEG4Main: entrypoint = VAEntrypointVLD; break; case VAProfileH264Baseline: case VAProfileH264Main: case VAProfileH264High: entrypoint = VAEntrypointVLD; break; case VAProfileVC1Simple: case VAProfileVC1Main: case VAProfileVC1Advanced: entrypoint = VAEntrypointVLD; break; default: entrypoint = 0; break; } if (entrypoint_list) *entrypoint_list = entrypoint; if (num_entrypoints) *num_entrypoints = entrypoint != 0; return VA_STATUS_SUCCESS; } // vaBeginPicture VAStatus vdpau_BeginPicture( VADriverContextP ctx, VAContextID context, VASurfaceID render_target ) { VDPAU_DRIVER_DATA_INIT; object_context_p obj_context = VDPAU_CONTEXT(context); if (!obj_context) return VA_STATUS_ERROR_INVALID_CONTEXT; object_surface_p obj_surface = VDPAU_SURFACE(render_target); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; obj_surface->va_surface_status = VASurfaceRendering; obj_context->last_pic_param = NULL; obj_context->last_slice_params = NULL; obj_context->last_slice_params_count = 0; obj_context->current_render_target = obj_surface->base.id; obj_context->gen_slice_data_size = 0; obj_context->vdp_bitstream_buffers_count = 0; switch (obj_context->vdp_codec) { case VDP_CODEC_MPEG1: case VDP_CODEC_MPEG2: obj_context->vdp_picture_info.mpeg2.slice_count = 0; break; case VDP_CODEC_MPEG4: break; case VDP_CODEC_H264: obj_context->vdp_picture_info.h264.slice_count = 0; break; case VDP_CODEC_VC1: obj_context->vdp_picture_info.vc1.slice_count = 0; break; default: return VA_STATUS_ERROR_UNKNOWN; } destroy_dead_va_buffers(driver_data, obj_context); return VA_STATUS_SUCCESS; } // vaRenderPicture VAStatus vdpau_RenderPicture( VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers ) { VDPAU_DRIVER_DATA_INIT; int i; object_context_p obj_context = VDPAU_CONTEXT(context); if (!obj_context) return VA_STATUS_ERROR_INVALID_CONTEXT; object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; /* Verify that we got valid buffer references */ for (i = 0; i < num_buffers; i++) { object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; } /* Translate buffers */ for (i = 0; i < num_buffers; i++) { object_buffer_p obj_buffer = VDPAU_BUFFER(buffers[i]); if (!translate_buffer(driver_data, obj_context, obj_buffer)) return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; /* Release any buffer that is not VASliceDataBuffer */ /* VASliceParameterBuffer is also needed to check for start_codes */ switch (obj_buffer->type) { case VASliceParameterBufferType: case VASliceDataBufferType: schedule_destroy_va_buffer(driver_data, obj_buffer); break; case VAPictureParameterBufferType: /* Preserve VAPictureParameterBufferMPEG4 */ if (obj_context->vdp_codec == VDP_CODEC_MPEG4) { schedule_destroy_va_buffer(driver_data, obj_buffer); break; } /* fall-through */ default: destroy_va_buffer(driver_data, obj_buffer); break; } buffers[i] = VA_INVALID_BUFFER; } return VA_STATUS_SUCCESS; } // vaEndPicture VAStatus vdpau_EndPicture( VADriverContextP ctx, VAContextID context ) { VDPAU_DRIVER_DATA_INIT; unsigned int i; object_context_p obj_context = VDPAU_CONTEXT(context); if (!obj_context) return VA_STATUS_ERROR_INVALID_CONTEXT; object_surface_p obj_surface = VDPAU_SURFACE(obj_context->current_render_target); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; if (trace_enabled()) { switch (obj_context->vdp_codec) { case VDP_CODEC_MPEG1: case VDP_CODEC_MPEG2: dump_VdpPictureInfoMPEG1Or2(&obj_context->vdp_picture_info.mpeg2); break; #if HAVE_VDPAU_MPEG4 case VDP_CODEC_MPEG4: dump_VdpPictureInfoMPEG4Part2(&obj_context->vdp_picture_info.mpeg4); break; #endif case VDP_CODEC_H264: dump_VdpPictureInfoH264(&obj_context->vdp_picture_info.h264); break; case VDP_CODEC_VC1: dump_VdpPictureInfoVC1(&obj_context->vdp_picture_info.vc1); break; default: break; } for (i = 0; i < obj_context->vdp_bitstream_buffers_count; i++) dump_VdpBitstreamBuffer(&obj_context->vdp_bitstream_buffers[i]); } VAStatus va_status; VdpStatus vdp_status; vdp_status = ensure_decoder_with_max_refs( driver_data, obj_context, get_num_ref_frames(obj_context) ); if (vdp_status == VDP_STATUS_OK) vdp_status = vdpau_decoder_render( driver_data, obj_context->vdp_decoder, obj_surface->vdp_surface, (VdpPictureInfo)&obj_context->vdp_picture_info, obj_context->vdp_bitstream_buffers_count, obj_context->vdp_bitstream_buffers ); va_status = vdpau_get_VAStatus(vdp_status); /* XXX: assume we are done with rendering right away */ obj_context->current_render_target = VA_INVALID_SURFACE; /* Release pending buffers */ destroy_dead_va_buffers(driver_data, obj_context); return va_status; } vdpau-driver-0.7.4/src/vdpau_decode.h000066400000000000000000000046311203356434100175210ustar00rootroot00000000000000/* * vdpau_decode.h - VDPAU backend for VA-API (decoder) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_DECODE_H #define VDPAU_DECODE_H #include "vdpau_driver.h" typedef enum { VDP_CODEC_MPEG1 = 1, VDP_CODEC_MPEG2, VDP_CODEC_MPEG4, VDP_CODEC_H264, VDP_CODEC_VC1 } VdpCodec; // Translates VdpDecoderProfile to VdpCodec VdpCodec get_VdpCodec(VdpDecoderProfile profile) attribute_hidden; // Translates VAProfile to VdpDecoderProfile VdpDecoderProfile get_VdpDecoderProfile(VAProfile profile) attribute_hidden; // Checks decoder for profile/entrypoint is available VAStatus check_decoder( vdpau_driver_data_t *driver_data, VAProfile profile, VAEntrypoint entrypoint ) attribute_hidden; // vaQueryConfigProfiles VAStatus vdpau_QueryConfigProfiles( VADriverContextP ctx, VAProfile *profile_list, int *num_profiles ) attribute_hidden; // vaQueryConfigEntrypoints VAStatus vdpau_QueryConfigEntrypoints( VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints ) attribute_hidden; // vaBeginPicture VAStatus vdpau_BeginPicture( VADriverContextP ctx, VAContextID context, VASurfaceID render_target ) attribute_hidden; // vaRenderPicture VAStatus vdpau_RenderPicture( VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers ) attribute_hidden; // vaEndPicture VAStatus vdpau_EndPicture( VADriverContextP ctx, VAContextID context ) attribute_hidden; #endif /* VDPAU_DECODE_H */ vdpau-driver-0.7.4/src/vdpau_driver.c000066400000000000000000000231441203356434100175640ustar00rootroot00000000000000/* * vdpau_driver.c - VDPAU driver * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include #include "vdpau_driver.h" #include "vdpau_buffer.h" #include "vdpau_decode.h" #include "vdpau_image.h" #include "vdpau_subpic.h" #include "vdpau_mixer.h" #include "vdpau_video.h" #include "vdpau_video_x11.h" #if USE_GLX #include "vdpau_video_glx.h" #include #endif #define DEBUG 1 #include "debug.h" // Set display type int vdpau_set_display_type(vdpau_driver_data_t *driver_data, unsigned int type) { if (driver_data->va_display_type == 0) { driver_data->va_display_type = type; return 1; } return driver_data->va_display_type == type; } // Return TRUE if underlying VDPAU implementation is NVIDIA VdpBool vdpau_is_nvidia(vdpau_driver_data_t *driver_data, int *major, int *minor) { uint32_t nvidia_version = 0; if (driver_data->vdp_impl_type == VDP_IMPLEMENTATION_NVIDIA) nvidia_version = driver_data->vdp_impl_version; if (major) *major = nvidia_version >> 16; if (minor) *minor = nvidia_version & 0xffff; return nvidia_version != 0; } // Translate VdpStatus to an appropriate VAStatus VAStatus vdpau_get_VAStatus(VdpStatus vdp_status) { VAStatus va_status; switch (vdp_status) { case VDP_STATUS_OK: va_status = VA_STATUS_SUCCESS; break; case VDP_STATUS_NO_IMPLEMENTATION: va_status = VA_STATUS_ERROR_UNIMPLEMENTED; break; case VDP_STATUS_INVALID_CHROMA_TYPE: va_status = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; break; case VDP_STATUS_INVALID_DECODER_PROFILE: va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; break; case VDP_STATUS_RESOURCES: va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; break; default: va_status = VA_STATUS_ERROR_UNKNOWN; break; } return va_status; } // Destroy BUFFER objects static void destroy_buffer_cb(object_base_p obj, void *user_data) { object_buffer_p const obj_buffer = (object_buffer_p)obj; vdpau_driver_data_t * const driver_data = user_data; destroy_va_buffer(driver_data, obj_buffer); } // Destroy MIXER objects static void destroy_mixer_cb(object_base_p obj, void *user_data) { object_mixer_p const obj_mixer = (object_mixer_p)obj; vdpau_driver_data_t * const driver_data = user_data; video_mixer_destroy(driver_data, obj_mixer); } // Destroy object heap typedef void (*destroy_heap_func_t)(object_base_p obj, void *user_data); static void destroy_heap( const char *name, object_heap_p heap, destroy_heap_func_t destroy_func, void *user_data ) { object_base_p obj; object_heap_iterator iter; if (!heap) return; obj = object_heap_first(heap, &iter); while (obj) { vdpau_information_message("vaTerminate(): %s ID 0x%08x is still allocated, destroying\n", name, obj->id); if (destroy_func) destroy_func(obj, user_data); else object_heap_free(heap, obj); obj = object_heap_next(heap, &iter); } object_heap_destroy(heap); } #define DESTROY_HEAP(heap, func) \ destroy_heap(#heap, &driver_data->heap##_heap, func, driver_data) #define CREATE_HEAP(type, id) do { \ int result; \ result = object_heap_init( \ &driver_data->type##_heap, \ sizeof(struct object_##type), \ VDPAU_##id##_ID_OFFSET \ ); \ if (result != 0) \ return VA_STATUS_ERROR_UNKNOWN; \ } while (0) // vaTerminate static void vdpau_common_Terminate(vdpau_driver_data_t *driver_data) { DESTROY_HEAP(buffer, destroy_buffer_cb); DESTROY_HEAP(image, NULL); DESTROY_HEAP(subpicture, NULL); DESTROY_HEAP(output, NULL); DESTROY_HEAP(surface, NULL); DESTROY_HEAP(context, NULL); DESTROY_HEAP(config, NULL); DESTROY_HEAP(mixer, destroy_mixer_cb); #if USE_GLX DESTROY_HEAP(glx_surface, NULL); #endif if (driver_data->vdp_device != VDP_INVALID_HANDLE) { vdpau_device_destroy(driver_data, driver_data->vdp_device); driver_data->vdp_device = VDP_INVALID_HANDLE; } vdpau_gate_exit(driver_data); if (driver_data->vdp_dpy) { XCloseDisplay(driver_data->vdp_dpy); driver_data->vdp_dpy = NULL; } } // vaInitialize static VAStatus vdpau_common_Initialize(vdpau_driver_data_t *driver_data) { /* Create a dedicated X11 display for VDPAU purposes */ const char * const x11_dpy_name = XDisplayString(driver_data->x11_dpy); driver_data->vdp_dpy = XOpenDisplay(x11_dpy_name); if (!driver_data->vdp_dpy) return VA_STATUS_ERROR_UNKNOWN; VdpStatus vdp_status; driver_data->vdp_device = VDP_INVALID_HANDLE; vdp_status = vdp_device_create_x11( driver_data->vdp_dpy, driver_data->x11_screen, &driver_data->vdp_device, &driver_data->vdp_get_proc_address ); if (vdp_status != VDP_STATUS_OK) return VA_STATUS_ERROR_UNKNOWN; if (vdpau_gate_init(driver_data) < 0) return VA_STATUS_ERROR_UNKNOWN; uint32_t api_version; vdp_status = vdpau_get_api_version(driver_data, &api_version); if (vdp_status != VDP_STATUS_OK) return vdpau_get_VAStatus(vdp_status); if (api_version != VDPAU_VERSION) return VA_STATUS_ERROR_UNKNOWN; const char *impl_string = NULL; vdp_status = vdpau_get_information_string(driver_data, &impl_string); if (vdp_status != VDP_STATUS_OK) return vdpau_get_VAStatus(vdp_status); if (impl_string) { const char *str, *version_string = NULL; D(bug("%s\n", impl_string)); if (strncmp(impl_string, "NVIDIA", 6) == 0) { /* NVIDIA VDPAU Driver Shared Library */ driver_data->vdp_impl_type = VDP_IMPLEMENTATION_NVIDIA; for (str = impl_string; *str; str++) { if (isdigit(*str)) { version_string = str; break; } } } if (version_string) { int major, minor; if (sscanf(version_string, "%d.%d", &major, &minor) == 2) driver_data->vdp_impl_version = (major << 16) | minor; } } sprintf(driver_data->va_vendor, "%s %s - %d.%d.%d", VDPAU_STR_DRIVER_VENDOR, VDPAU_STR_DRIVER_NAME, VDPAU_VIDEO_MAJOR_VERSION, VDPAU_VIDEO_MINOR_VERSION, VDPAU_VIDEO_MICRO_VERSION); if (VDPAU_VIDEO_PRE_VERSION > 0) { const int len = strlen(driver_data->va_vendor); sprintf(&driver_data->va_vendor[len], ".pre%d", VDPAU_VIDEO_PRE_VERSION); } CREATE_HEAP(config, CONFIG); CREATE_HEAP(context, CONTEXT); CREATE_HEAP(surface, SURFACE); CREATE_HEAP(buffer, BUFFER); CREATE_HEAP(output, OUTPUT); CREATE_HEAP(image, IMAGE); CREATE_HEAP(subpicture, SUBPICTURE); CREATE_HEAP(mixer, MIXER); #if USE_GLX CREATE_HEAP(glx_surface, GLX_SURFACE); #endif return VA_STATUS_SUCCESS; } #if VA_MAJOR_VERSION == 0 && VA_MINOR_VERSION >= 31 #define VA_INIT_VERSION_MAJOR 0 #define VA_INIT_VERSION_MINOR 31 #define VA_INIT_VERSION_MICRO 0 #define VA_INIT_SUFFIX 0_31_0 #include "vdpau_driver_template.h" #define VA_INIT_VERSION_MAJOR 0 #define VA_INIT_VERSION_MINOR 31 #define VA_INIT_VERSION_MICRO 1 #define VA_INIT_SUFFIX 0_31_1 #define VA_INIT_GLX USE_GLX #include "vdpau_driver_template.h" #define VA_INIT_VERSION_MAJOR 0 #define VA_INIT_VERSION_MINOR 31 #define VA_INIT_VERSION_MICRO 2 #define VA_INIT_SUFFIX 0_31_2 #define VA_INIT_GLX USE_GLX #include "vdpau_driver_template.h" VAStatus __vaDriverInit_0_31(void *ctx) { VADriverContextP_0_31_0 const ctx0 = ctx; VADriverContextP_0_31_1 const ctx1 = ctx; VADriverContextP_0_31_2 const ctx2 = ctx; /* Assume a NULL display implies VA-API 0.31.1 struct with the vtable_tpi field placed just after the vtable, thus replacing original native_dpy field */ if (ctx0->native_dpy) return vdpau_Initialize_0_31_0(ctx); if (ctx1->native_dpy) return vdpau_Initialize_0_31_1(ctx); if (ctx2->native_dpy) return vdpau_Initialize_0_31_2(ctx); return VA_STATUS_ERROR_INVALID_DISPLAY; } #endif #define VA_INIT_VERSION_MAJOR VA_MAJOR_VERSION #define VA_INIT_VERSION_MINOR VA_MINOR_VERSION #define VA_INIT_VERSION_MICRO VA_MICRO_VERSION #define VA_INIT_GLX USE_GLX #include "vdpau_driver_template.h" VAStatus VA_DRIVER_INIT_FUNC(void *ctx) { #if VA_MAJOR_VERSION == 0 && VA_MINOR_VERSION == 31 return __vaDriverInit_0_31(ctx); #endif return vdpau_Initialize_Current(ctx); } vdpau-driver-0.7.4/src/vdpau_driver.h000066400000000000000000000121511203356434100175650ustar00rootroot00000000000000/* * vdpau_driver.h - VDPAU driver * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_DRIVER_H #define VDPAU_DRIVER_H #include #include "vaapi_compat.h" #include "vdpau_gate.h" #include "object_heap.h" #define VDPAU_DRIVER_DATA_INIT \ struct vdpau_driver_data *driver_data = \ (struct vdpau_driver_data *)ctx->pDriverData #define VDPAU_OBJECT(id, type) \ ((object_##type##_p)object_heap_lookup(&driver_data->type##_heap, (id))) #define VDPAU_CONFIG(id) VDPAU_OBJECT(id, config) #define VDPAU_CONTEXT(id) VDPAU_OBJECT(id, context) #define VDPAU_SURFACE(id) VDPAU_OBJECT(id, surface) #define VDPAU_BUFFER(id) VDPAU_OBJECT(id, buffer) #define VDPAU_OUTPUT(id) VDPAU_OBJECT(id, output) #define VDPAU_IMAGE(id) VDPAU_OBJECT(id, image) #define VDPAU_GLX_SURFACE(id) VDPAU_OBJECT(id, glx_surface) #define VDPAU_SUBPICTURE(id) VDPAU_OBJECT(id, subpicture) #define VDPAU_MIXER(id) VDPAU_OBJECT(id, mixer) #define VDPAU_CONFIG_ID_OFFSET 0x01000000 #define VDPAU_CONTEXT_ID_OFFSET 0x02000000 #define VDPAU_SURFACE_ID_OFFSET 0x03000000 #define VDPAU_BUFFER_ID_OFFSET 0x04000000 #define VDPAU_OUTPUT_ID_OFFSET 0x05000000 #define VDPAU_IMAGE_ID_OFFSET 0x06000000 #define VDPAU_SUBPICTURE_ID_OFFSET 0x07000000 #define VDPAU_GLX_SURFACE_ID_OFFSET 0x08000000 #define VDPAU_MIXER_ID_OFFSET 0x09000000 #define VDPAU_MAX_PROFILES 12 #define VDPAU_MAX_ENTRYPOINTS 5 #define VDPAU_MAX_CONFIG_ATTRIBUTES 10 #define VDPAU_MAX_IMAGE_FORMATS 10 #define VDPAU_MAX_SUBPICTURES 8 #define VDPAU_MAX_SUBPICTURE_FORMATS 6 #define VDPAU_MAX_DISPLAY_ATTRIBUTES 6 #define VDPAU_MAX_OUTPUT_SURFACES 2 #define VDPAU_STR_DRIVER_VENDOR "Splitted-Desktop Systems" #define VDPAU_STR_DRIVER_NAME "VDPAU backend for VA-API" /* Check we have MPEG-4 support in VDPAU and the necessary VAAPI extensions */ #define USE_VDPAU_MPEG4 \ (HAVE_VDPAU_MPEG4 && \ (VA_CHECK_VERSION(0,31,1) || \ (VA_CHECK_VERSION(0,31,0) && VA_SDS_VERSION >= 4))) typedef enum { VDP_IMPLEMENTATION_NVIDIA = 1, } VdpImplementation; typedef struct vdpau_driver_data vdpau_driver_data_t; struct vdpau_driver_data { VADriverContextP va_context; unsigned int va_display_type; struct object_heap config_heap; struct object_heap context_heap; struct object_heap surface_heap; struct object_heap glx_surface_heap; struct object_heap buffer_heap; struct object_heap output_heap; struct object_heap image_heap; struct object_heap subpicture_heap; struct object_heap mixer_heap; Display *x11_dpy; int x11_screen; Display *vdp_dpy; VdpDevice vdp_device; VdpGetProcAddress *vdp_get_proc_address; vdpau_vtable_t vdp_vtable; VdpImplementation vdp_impl_type; uint32_t vdp_impl_version; VADisplayAttribute va_display_attrs[VDPAU_MAX_DISPLAY_ATTRIBUTES]; uint64_t va_display_attrs_mtime[VDPAU_MAX_DISPLAY_ATTRIBUTES]; unsigned int va_display_attrs_count; char va_vendor[256]; }; typedef struct object_config *object_config_p; typedef struct object_context *object_context_p; typedef struct object_surface *object_surface_p; typedef struct object_buffer *object_buffer_p; typedef struct object_output *object_output_p; typedef struct object_image *object_image_p; typedef struct object_mixer *object_mixer_p; // Set display type int vdpau_set_display_type(vdpau_driver_data_t *driver_data, unsigned int type) attribute_hidden; // Return TRUE if underlying VDPAU implementation is NVIDIA VdpBool vdpau_is_nvidia(vdpau_driver_data_t *driver_data, int *major, int *minor) attribute_hidden; // Translate VdpStatus to an appropriate VAStatus VAStatus vdpau_get_VAStatus(VdpStatus vdp_status) attribute_hidden; #endif /* VDPAU_DRIVER_H */ vdpau-driver-0.7.4/src/vdpau_driver_template.h000066400000000000000000000502301203356434100214600ustar00rootroot00000000000000/* * vdpau_driver_template.h - VDPAU driver initialization template * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #undef CONCAT_ #define CONCAT_(x, y) x##y #undef CONCAT #define CONCAT(x, y) CONCAT_(x, y) #undef FUNC #define FUNC(name) CONCAT(CONCAT(CONCAT(vdpau_,name),_),VA_INIT_SUFFIX) #undef VA_INIT_CHECK_VERSION #define VA_INIT_CHECK_VERSION(major, minor, micro) \ (VA_INIT_VERSION_MAJOR > (major) || \ (VA_INIT_VERSION_MAJOR == (major) && \ VA_INIT_VERSION_MINOR > (minor)) || \ (VA_INIT_VERSION_MAJOR == (major) && \ VA_INIT_VERSION_MINOR == (minor) && \ VA_INIT_VERSION_MICRO >= (micro))) #undef VA_INIT_CHECK_VERSION_SDS #define VA_INIT_CHECK_VERSION_SDS(major, minor, micro, sds) \ (VA_INIT_CHECK_VERSION(major, minor, (micro)+1) || \ (VA_INIT_CHECK_VERSION(major, minor, micro) && \ VA_INIT_VERSION_SDS >= (sds))) #ifndef VA_INIT_SUFFIX #define VA_INIT_SUFFIX Current #define VA_INIT_CURRENT 1 #else #define VA_INIT_CURRENT 0 #endif #ifndef VA_INIT_VERSION_SDS #define VA_INIT_VERSION_SDS 0 #endif #ifndef VA_INIT_GLX #define VA_INIT_GLX 0 #endif #if VA_INIT_CURRENT #define VA_DRIVER_VTABLE VADriverVTable #define VA_DRIVER_CONTEXT VADriverContext #define VA_DRIVER_CONTEXT_P VADriverContextP #else #define VA_DRIVER_VTABLE CONCAT(VADriverVTable_,VA_INIT_SUFFIX) #define VA_DRIVER_VTABLE_GLX_P CONCAT(VADriverVTableGLX_,VA_INIT_SUFFIX) #define VA_DRIVER_CONTEXT CONCAT(VADriverContext_,VA_INIT_SUFFIX) #define VA_DRIVER_CONTEXT_P CONCAT(VADriverContextP_,VA_INIT_SUFFIX) typedef struct VA_DRIVER_CONTEXT *VA_DRIVER_CONTEXT_P; /* Driver VTable */ struct VA_DRIVER_VTABLE { VAStatus (*vaTerminate) ( VA_DRIVER_CONTEXT_P ctx ); VAStatus (*vaQueryConfigProfiles) ( VADriverContextP ctx, VAProfile *profile_list, /* out */ int *num_profiles /* out */ ); VAStatus (*vaQueryConfigEntrypoints) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, /* out */ int *num_entrypoints /* out */ ); VAStatus (*vaGetConfigAttributes) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, /* in/out */ int num_attribs ); VAStatus (*vaCreateConfig) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id /* out */ ); VAStatus (*vaDestroyConfig) ( VADriverContextP ctx, VAConfigID config_id ); VAStatus (*vaQueryConfigAttributes) ( VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, /* out */ VAEntrypoint *entrypoint, /* out */ VAConfigAttrib *attrib_list, /* out */ int *num_attribs /* out */ ); VAStatus (*vaCreateSurfaces) ( VADriverContextP ctx, int width, int height, int format, int num_surfaces, VASurfaceID *surfaces /* out */ ); VAStatus (*vaDestroySurfaces) ( VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces ); VAStatus (*vaCreateContext) ( VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context /* out */ ); VAStatus (*vaDestroyContext) ( VADriverContextP ctx, VAContextID context ); VAStatus (*vaCreateBuffer) ( VADriverContextP ctx, VAContextID context, /* in */ VABufferType type, /* in */ unsigned int size, /* in */ unsigned int num_elements, /* in */ void *data, /* in */ VABufferID *buf_id /* out */ ); VAStatus (*vaBufferSetNumElements) ( VADriverContextP ctx, VABufferID buf_id, /* in */ unsigned int num_elements /* in */ ); VAStatus (*vaMapBuffer) ( VADriverContextP ctx, VABufferID buf_id, /* in */ void **pbuf /* out */ ); VAStatus (*vaUnmapBuffer) ( VADriverContextP ctx, VABufferID buf_id /* in */ ); VAStatus (*vaDestroyBuffer) ( VADriverContextP ctx, VABufferID buffer_id ); VAStatus (*vaBeginPicture) ( VADriverContextP ctx, VAContextID context, VASurfaceID render_target ); VAStatus (*vaRenderPicture) ( VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers ); VAStatus (*vaEndPicture) ( VADriverContextP ctx, VAContextID context ); VAStatus (*vaSyncSurface) ( VADriverContextP ctx, VASurfaceID render_target ); VAStatus (*vaQuerySurfaceStatus) ( VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status /* out */ ); #if VA_INIT_CHECK_VERSION(0,31,2) VAStatus (*vaQuerySurfaceError) ( VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info /*out*/ ); #endif VAStatus (*vaPutSurface) ( VADriverContextP ctx, VASurfaceID surface, VADrawable draw, /* X Drawable */ short srcx, short srcy, unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, unsigned short desth, VARectangle *cliprects, /* client supplied clip list */ unsigned int number_cliprects, /* number of clip rects in the clip list */ unsigned int flags /* de-interlacing flags */ ); VAStatus (*vaQueryImageFormats) ( VADriverContextP ctx, VAImageFormat *format_list, /* out */ int *num_formats /* out */ ); VAStatus (*vaCreateImage) ( VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image /* out */ ); VAStatus (*vaDeriveImage) ( VADriverContextP ctx, VASurfaceID surface, VAImage *image /* out */ ); VAStatus (*vaDestroyImage) ( VADriverContextP ctx, VAImageID image ); VAStatus (*vaSetImagePalette) ( VADriverContextP ctx, VAImageID image, /* * pointer to an array holding the palette data. The size of the array is * num_palette_entries * entry_bytes in size. The order of the components * in the palette is described by the component_order in VAImage struct */ unsigned char *palette ); VAStatus (*vaGetImage) ( VADriverContextP ctx, VASurfaceID surface, int x, /* coordinates of the upper left source pixel */ int y, unsigned int width, /* width and height of the region */ unsigned int height, VAImageID image ); VAStatus (*vaPutImage) ( VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height ); VAStatus (*vaQuerySubpictureFormats) ( VADriverContextP ctx, VAImageFormat *format_list, /* out */ unsigned int *flags, /* out */ unsigned int *num_formats /* out */ ); VAStatus (*vaCreateSubpicture) ( VADriverContextP ctx, VAImageID image, VASubpictureID *subpicture /* out */ ); VAStatus (*vaDestroySubpicture) ( VADriverContextP ctx, VASubpictureID subpicture ); VAStatus (*vaSetSubpictureImage) ( VADriverContextP ctx, VASubpictureID subpicture, VAImageID image ); VAStatus (*vaSetSubpictureChromakey) ( VADriverContextP ctx, VASubpictureID subpicture, unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask ); VAStatus (*vaSetSubpictureGlobalAlpha) ( VADriverContextP ctx, VASubpictureID subpicture, float global_alpha ); VAStatus (*vaAssociateSubpicture) ( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces, short src_x, /* upper left offset in subpicture */ short src_y, unsigned short src_width, unsigned short src_height, short dest_x, /* upper left offset in surface */ short dest_y, unsigned short dest_width, unsigned short dest_height, /* * whether to enable chroma-keying or global-alpha * see VA_SUBPICTURE_XXX values */ unsigned int flags ); VAStatus (*vaDeassociateSubpicture) ( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces ); VAStatus (*vaQueryDisplayAttributes) ( VADriverContextP ctx, VADisplayAttribute *attr_list, /* out */ int *num_attributes /* out */ ); VAStatus (*vaGetDisplayAttributes) ( VADriverContextP ctx, VADisplayAttribute *attr_list, /* in/out */ int num_attributes ); VAStatus (*vaSetDisplayAttributes) ( VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes ); #if VA_INIT_CHECK_VERSION(0,31,1) /* used by va trace */ VAStatus (*vaBufferInfo) ( VADriverContextP ctx, VAContextID context, /* in */ VABufferID buf_id, /* in */ VABufferType *type, /* out */ unsigned int *size, /* out */ unsigned int *num_elements /* out */ ); /* lock/unlock surface for external access */ VAStatus (*vaLockSurface) ( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, /* out for follow argument */ unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, unsigned int *buffer_name, /* if it is not NULL, assign the low lever * surface buffer name */ void **buffer /* if it is not NULL, map the surface buffer for * CPU access */ ); VAStatus (*vaUnlockSurface) ( VADriverContextP ctx, VASurfaceID surface ); #if !VA_INIT_CHECK_VERSION(0,32,0) /* Optional: GLX support hooks */ struct VADriverVTableGLX *glx; #endif #else /* device specific */ VAStatus (*vaCreateSurfaceFromCIFrame) ( VADriverContextP ctx, unsigned long frame_id, VASurfaceID *surface /* out */ ); VAStatus (*vaCreateSurfaceFromV4L2Buf) ( VADriverContextP ctx, int v4l2_fd, /* file descriptor of V4L2 device */ struct v4l2_format *v4l2_fmt, /* format of V4L2 */ struct v4l2_buffer *v4l2_buf, /* V4L2 buffer */ VASurfaceID *surface /* out */ ); VAStatus (*vaCopySurfaceToBuffer) ( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, /* out for follow argument */ unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, void **buffer ); #endif }; /* Driver context */ struct VA_DRIVER_CONTEXT { void *pDriverData; #if VA_INIT_CHECK_VERSION(0,32,0) struct VA_DRIVER_VTABLE *vtable; struct VADriverVTableGLX *vtable_glx; struct VADriverVTableEGL *vtable_egl; #else struct VA_DRIVER_VTABLE vtable; #endif #if VA_INIT_CHECK_VERSION(0,31,1) void *vtable_tpi; /* the structure is malloc-ed */ #endif Display *native_dpy; int x11_screen; int version_major; int version_minor; int max_profiles; int max_entrypoints; int max_attributes; int max_image_formats; int max_subpic_formats; int max_display_attributes; const char *str_vendor; void *handle; /* dlopen handle */ void *dri_state; #if VA_INIT_CHECK_VERSION(0,31,1) void *glx; /* opaque for GLX code */ #endif }; #endif // Check for VA/GLX changes from libVA API >= 0.31.0-sds2 #if VA_INIT_GLX #if VA_INIT_CHECK_VERSION_SDS(0,31,0,2) typedef struct VADriverVTableGLX *VA_DRIVER_VTABLE_GLX_P; #else typedef struct VA_DRIVER_VTABLE *VA_DRIVER_VTABLE_GLX_P; #endif static inline VA_DRIVER_VTABLE_GLX_P FUNC(GetVTableGLX)(VA_DRIVER_CONTEXT_P ctx) { #if VA_INIT_CHECK_VERSION_SDS(0,31,0,6) #if VA_INIT_CHECK_VERSION(0,32,0) /* Upstream VA-API 0.32 */ VA_DRIVER_VTABLE_GLX_P *p_vtable_glx = &ctx->vtable_glx; #else /* Upstream VA-API 0.31.1 or SDS >= 0.31.0-sds6 */ VA_DRIVER_VTABLE_GLX_P *p_vtable_glx = &ctx->vtable.glx; #endif VA_DRIVER_VTABLE_GLX_P vtable_glx = *p_vtable_glx; if (!vtable_glx) { vtable_glx = calloc(1, sizeof(*vtable_glx)); if (!vtable_glx) return NULL; *p_vtable_glx = vtable_glx; } return vtable_glx; #elif VA_INIT_CHECK_VERSION_SDS(0,31,0,2) /* SDS >= 0.31.0-sds2 */ return &ctx->vtable.glx; #else /* Any other VA-API version 0.31.0 or lower */ return &ctx->vtable; #endif } static inline void FUNC(ReleaseVTableGLX)(VA_DRIVER_CONTEXT_P ctx) { #if VA_INIT_CHECK_VERSION(0,32,0) free(ctx->vtable_glx); ctx->vtable_glx = NULL; #elif VA_INIT_CHECK_VERSION_SDS(0,31,0,6) free(ctx->vtable.glx); ctx->vtable.glx = NULL; #endif } #endif static VAStatus FUNC(Terminate)(VA_DRIVER_CONTEXT_P ctx) { VDPAU_DRIVER_DATA_INIT; vdpau_common_Terminate(driver_data); #if VA_INIT_GLX FUNC(ReleaseVTableGLX)(ctx); #endif free(ctx->pDriverData); ctx->pDriverData = NULL; return VA_STATUS_SUCCESS; } static VAStatus FUNC(Initialize)(VA_DRIVER_CONTEXT_P ctx) { struct vdpau_driver_data *driver_data; driver_data = calloc(1, sizeof(*driver_data)); if (!driver_data) return VA_STATUS_ERROR_ALLOCATION_FAILED; ctx->pDriverData = driver_data; driver_data->x11_dpy = ctx->native_dpy; driver_data->x11_screen = ctx->x11_screen; VAStatus va_status = vdpau_common_Initialize(driver_data); if (va_status != VA_STATUS_SUCCESS) { FUNC(Terminate)(ctx); return va_status; } ctx->version_major = VA_INIT_VERSION_MAJOR; ctx->version_minor = VA_INIT_VERSION_MINOR; ctx->max_profiles = VDPAU_MAX_PROFILES; ctx->max_entrypoints = VDPAU_MAX_ENTRYPOINTS; ctx->max_attributes = VDPAU_MAX_CONFIG_ATTRIBUTES; ctx->max_image_formats = VDPAU_MAX_IMAGE_FORMATS; ctx->max_subpic_formats = VDPAU_MAX_SUBPICTURE_FORMATS; ctx->max_display_attributes = VDPAU_MAX_DISPLAY_ATTRIBUTES; ctx->str_vendor = driver_data->va_vendor; struct VA_DRIVER_VTABLE *vtable; #if VA_INIT_CHECK_VERSION(0,32,0) vtable = ctx->vtable; #else vtable = &ctx->vtable; #endif memset(vtable, 0, sizeof(*vtable)); vtable->vaTerminate = FUNC(Terminate); vtable->vaQueryConfigEntrypoints = vdpau_QueryConfigEntrypoints; vtable->vaQueryConfigProfiles = vdpau_QueryConfigProfiles; vtable->vaQueryConfigEntrypoints = vdpau_QueryConfigEntrypoints; vtable->vaQueryConfigAttributes = vdpau_QueryConfigAttributes; vtable->vaCreateConfig = vdpau_CreateConfig; vtable->vaDestroyConfig = vdpau_DestroyConfig; vtable->vaGetConfigAttributes = vdpau_GetConfigAttributes; vtable->vaCreateSurfaces = vdpau_CreateSurfaces; vtable->vaDestroySurfaces = vdpau_DestroySurfaces; vtable->vaCreateContext = vdpau_CreateContext; vtable->vaDestroyContext = vdpau_DestroyContext; vtable->vaCreateBuffer = vdpau_CreateBuffer; vtable->vaBufferSetNumElements = vdpau_BufferSetNumElements; vtable->vaMapBuffer = vdpau_MapBuffer; vtable->vaUnmapBuffer = vdpau_UnmapBuffer; vtable->vaDestroyBuffer = vdpau_DestroyBuffer; vtable->vaBeginPicture = vdpau_BeginPicture; vtable->vaRenderPicture = vdpau_RenderPicture; vtable->vaEndPicture = vdpau_EndPicture; #if VA_INIT_CHECK_VERSION(0,31,0) vtable->vaSyncSurface = vdpau_SyncSurface2; #else vtable->vaSyncSurface = vdpau_SyncSurface3; #endif vtable->vaQuerySurfaceStatus = vdpau_QuerySurfaceStatus; vtable->vaPutSurface = vdpau_PutSurface; vtable->vaQueryImageFormats = vdpau_QueryImageFormats; vtable->vaCreateImage = vdpau_CreateImage; vtable->vaDeriveImage = vdpau_DeriveImage; vtable->vaDestroyImage = vdpau_DestroyImage; vtable->vaSetImagePalette = vdpau_SetImagePalette; vtable->vaGetImage = vdpau_GetImage; #if VA_INIT_CHECK_VERSION(0,31,0) vtable->vaPutImage = vdpau_PutImage_full; #else vtable->vaPutImage = vdpau_PutImage; vtable->vaPutImage2 = vdpau_PutImage_full; #endif vtable->vaQuerySubpictureFormats = vdpau_QuerySubpictureFormats; vtable->vaCreateSubpicture = vdpau_CreateSubpicture; vtable->vaDestroySubpicture = vdpau_DestroySubpicture; vtable->vaSetSubpictureImage = vdpau_SetSubpictureImage; vtable->vaSetSubpictureChromakey = vdpau_SetSubpictureChromakey; vtable->vaSetSubpictureGlobalAlpha = vdpau_SetSubpictureGlobalAlpha; #if VA_INIT_CHECK_VERSION(0,31,0) vtable->vaAssociateSubpicture = vdpau_AssociateSubpicture_full; #else vtable->vaAssociateSubpicture = vdpau_AssociateSubpicture; vtable->vaAssociateSubpicture2 = vdpau_AssociateSubpicture_full; #endif vtable->vaDeassociateSubpicture = vdpau_DeassociateSubpicture; vtable->vaQueryDisplayAttributes = vdpau_QueryDisplayAttributes; vtable->vaGetDisplayAttributes = vdpau_GetDisplayAttributes; vtable->vaSetDisplayAttributes = vdpau_SetDisplayAttributes; #if VA_INIT_CHECK_VERSION(0,31,1) #if VA_INIT_CHECK_VERSION(0,32,0) vtable->vaBufferInfo = vdpau_BufferInfo; #else vtable->vaBufferInfo = vdpau_BufferInfo_0_31_1; #endif vtable->vaLockSurface = vdpau_LockSurface; vtable->vaUnlockSurface = vdpau_UnlockSurface; #else #if VA_INIT_CHECK_VERSION(0,30,0) vtable->vaCreateSurfaceFromCIFrame = vdpau_CreateSurfaceFromCIFrame; vtable->vaCreateSurfaceFromV4L2Buf = vdpau_CreateSurfaceFromV4L2Buf; vtable->vaCopySurfaceToBuffer = vdpau_CopySurfaceToBuffer; #else vtable->vaSetSubpicturePalette = vdpau_SetSubpicturePalette; vtable->vaDbgCopySurfaceToBuffer = vdpau_DbgCopySurfaceToBuffer; #endif #endif #if VA_INIT_GLX VA_DRIVER_VTABLE_GLX_P const glx_vtable = FUNC(GetVTableGLX)(ctx); if (!glx_vtable) return VA_STATUS_ERROR_ALLOCATION_FAILED; glx_vtable->vaCreateSurfaceGLX = vdpau_CreateSurfaceGLX; glx_vtable->vaDestroySurfaceGLX = vdpau_DestroySurfaceGLX; glx_vtable->vaCopySurfaceGLX = vdpau_CopySurfaceGLX; #endif return VA_STATUS_SUCCESS; } #undef VA_INIT_CURRENT #undef VA_INIT_VERSION_MAJOR #undef VA_INIT_VERSION_MINOR #undef VA_INIT_VERSION_MICRO #undef VA_INIT_VERSION_SDS #undef VA_INIT_SUFFIX #undef VA_INIT_GLX #undef VA_DRIVER_VTABLE #undef VA_DRIVER_VTABLE_GLX_P #undef VA_DRIVER_CONTEXT #undef VA_DRIVER_CONTEXT_P vdpau-driver-0.7.4/src/vdpau_dump.c000066400000000000000000000230511203356434100172330ustar00rootroot00000000000000/* * vdpau_dump.c - Dump utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_dump.h" #define DEBUG 1 #include "debug.h" // Returns string representation of FOURCC const char *string_of_FOURCC(uint32_t fourcc) { static char str[5]; str[0] = fourcc; str[1] = fourcc >> 8; str[2] = fourcc >> 16; str[3] = fourcc >> 24; str[4] = '\0'; return str; } // Returns string representation of VABufferType const char *string_of_VABufferType(VABufferType type) { const char *str = NULL; switch (type) { #define _(X) case X: str = #X; break _(VAPictureParameterBufferType); _(VAIQMatrixBufferType); _(VABitPlaneBufferType); _(VASliceGroupMapBufferType); _(VASliceParameterBufferType); _(VASliceDataBufferType); _(VAMacroblockParameterBufferType); _(VAResidualDataBufferType); _(VADeblockingParameterBufferType); _(VAImageBufferType); #if VA_CHECK_VERSION(0,30,0) _(VAProtectedSliceDataBufferType); _(VAEncCodedBufferType); _(VAEncSequenceParameterBufferType); _(VAEncPictureParameterBufferType); _(VAEncSliceParameterBufferType); _(VAEncH264VUIBufferType); _(VAEncH264SEIBufferType); #endif #if VA_CHECK_VERSION(0,31,1) _(VAQMatrixBufferType); #endif #if VA_CHECK_VERSION(0,32,0) _(VAEncMiscParameterBufferType); #endif default: break; #undef _ } return str; } // Returns string representation of VdpCodec const char *string_of_VdpCodec(VdpCodec codec) { const char *str = NULL; switch (codec) { #define _(X) case VDP_CODEC_##X: str = #X; break _(MPEG1); _(MPEG2); _(MPEG4); _(H264); _(VC1); #undef _ } return str; } #if USE_TRACER #define TRACE trace_print #define INDENT(INC) trace_indent(INC) #define DUMPi(S, M) TRACE("." #M " = %d,\n", S->M) #define DUMPx(S, M) TRACE("." #M " = 0x%08x,\n", S->M) #define DUMPp(S, M) TRACE("." #M " = %p,\n", S->M) #define DUMPm(S, M, I, J) dump_matrix_NxM(#M, (uint8_t *)S->M, I, J, I * J) #else #define trace_enabled() (0) #define do_nothing() do { } while (0) #define TRACE(FORMAT,...) do_nothing() #define INDENT(INC) do_nothing() #define DUMPi(S, M) do_nothing() #define DUMPx(S, M) do_nothing() #define DUMPp(S, M) do_nothing() #define DUMPm(S, M, I, J) do_nothing() #endif // Dumps matrix[N][M] = N rows x M columns (uint8_t) static void dump_matrix_NxM(const char *label, const uint8_t *matrix, int N, int M, int L) { int i, j, n = 0; TRACE(".%s = {\n", label); INDENT(1); for (j = 0; j < N; j++) { for (i = 0; i < M; i++, n++) { if (n >= L) break; if (i > 0) TRACE(", "); TRACE("0x%02x", matrix[n]); } if (j < (N - 1)) TRACE(","); TRACE("\n"); if (n >= L) break; } INDENT(-1); TRACE("}\n"); } // Dumps VdpPictureInfoMPEG1Or2 void dump_VdpPictureInfoMPEG1Or2(VdpPictureInfoMPEG1Or2 *pic_info) { INDENT(1); TRACE("VdpPictureInfoMPEG1Or2 = {\n"); INDENT(1); DUMPx(pic_info, forward_reference); DUMPx(pic_info, backward_reference); DUMPi(pic_info, slice_count); DUMPi(pic_info, picture_structure); DUMPi(pic_info, picture_coding_type); DUMPi(pic_info, intra_dc_precision); DUMPi(pic_info, frame_pred_frame_dct); DUMPi(pic_info, concealment_motion_vectors); DUMPi(pic_info, intra_vlc_format); DUMPi(pic_info, alternate_scan); DUMPi(pic_info, q_scale_type); DUMPi(pic_info, top_field_first); DUMPi(pic_info, full_pel_forward_vector); DUMPi(pic_info, full_pel_backward_vector); TRACE(".f_code = { { %d, %d }, { %d, %d } };\n", pic_info->f_code[0][0], pic_info->f_code[0][1], pic_info->f_code[1][0], pic_info->f_code[1][1]); DUMPm(pic_info, intra_quantizer_matrix, 8, 8); DUMPm(pic_info, non_intra_quantizer_matrix, 8, 8); INDENT(-1); TRACE("};\n"); INDENT(-1); } // Dumps VdpPictureInfoMPEG4Part2 #if HAVE_VDPAU_MPEG4 void dump_VdpPictureInfoMPEG4Part2(VdpPictureInfoMPEG4Part2 *pic_info) { INDENT(1); TRACE("VdpPictureInfoMPEG4Part2 = {\n"); INDENT(1); DUMPx(pic_info, forward_reference); DUMPx(pic_info, backward_reference); DUMPi(pic_info, vop_time_increment_resolution); DUMPi(pic_info, vop_coding_type); DUMPi(pic_info, vop_fcode_forward); DUMPi(pic_info, vop_fcode_backward); DUMPi(pic_info, resync_marker_disable); DUMPi(pic_info, interlaced); DUMPi(pic_info, quant_type); DUMPi(pic_info, quarter_sample); DUMPi(pic_info, short_video_header); DUMPi(pic_info, rounding_control); DUMPi(pic_info, alternate_vertical_scan_flag); DUMPi(pic_info, top_field_first); DUMPm(pic_info, intra_quantizer_matrix, 8, 8); DUMPm(pic_info, non_intra_quantizer_matrix, 8, 8); INDENT(-1); TRACE("};\n"); INDENT(-1); } #endif // Dumps VdpReferenceFrameH264 static void dump_VdpReferenceFrameH264(VdpReferenceFrameH264 *rf, const char *label) { TRACE(".%s = {\n", label); INDENT(1); DUMPx(rf, surface); DUMPi(rf, is_long_term); DUMPi(rf, top_is_reference); DUMPi(rf, bottom_is_reference); DUMPi(rf, field_order_cnt[0]); DUMPi(rf, field_order_cnt[1]); DUMPi(rf, frame_idx); INDENT(-1); TRACE("}\n"); } // Dumps VdpPictureInfoH264 void dump_VdpPictureInfoH264(VdpPictureInfoH264 *pic_info) { int i; INDENT(1); TRACE("VdpPictureInfoH264 = {\n"); INDENT(1); DUMPi(pic_info, slice_count); DUMPi(pic_info, field_order_cnt[0]); DUMPi(pic_info, field_order_cnt[1]); DUMPi(pic_info, is_reference); DUMPi(pic_info, frame_num); DUMPi(pic_info, field_pic_flag); DUMPi(pic_info, bottom_field_flag); DUMPi(pic_info, num_ref_frames); DUMPi(pic_info, mb_adaptive_frame_field_flag); DUMPi(pic_info, constrained_intra_pred_flag); DUMPi(pic_info, weighted_pred_flag); DUMPi(pic_info, weighted_bipred_idc); DUMPi(pic_info, frame_mbs_only_flag); DUMPi(pic_info, transform_8x8_mode_flag); DUMPi(pic_info, chroma_qp_index_offset); DUMPi(pic_info, second_chroma_qp_index_offset); DUMPi(pic_info, pic_init_qp_minus26); DUMPi(pic_info, num_ref_idx_l0_active_minus1); DUMPi(pic_info, num_ref_idx_l1_active_minus1); DUMPi(pic_info, log2_max_frame_num_minus4); DUMPi(pic_info, pic_order_cnt_type); DUMPi(pic_info, log2_max_pic_order_cnt_lsb_minus4); DUMPi(pic_info, delta_pic_order_always_zero_flag); DUMPi(pic_info, direct_8x8_inference_flag); DUMPi(pic_info, entropy_coding_mode_flag); DUMPi(pic_info, pic_order_present_flag); DUMPi(pic_info, deblocking_filter_control_present_flag); DUMPi(pic_info, redundant_pic_cnt_present_flag); DUMPm(pic_info, scaling_lists_4x4, 6, 16); DUMPm(pic_info, scaling_lists_8x8[0], 8, 8); DUMPm(pic_info, scaling_lists_8x8[1], 8, 8); for (i = 0; i < 16; i++) { char label[100]; sprintf(label, "referenceFrames[%d]", i); dump_VdpReferenceFrameH264(&pic_info->referenceFrames[i], label); } INDENT(-1); TRACE("};\n"); INDENT(-1); } // Dumps VdpPictureInfoVC1 void dump_VdpPictureInfoVC1(VdpPictureInfoVC1 *pic_info) { INDENT(1); TRACE("VdpPictureInfoVC1 = {\n"); INDENT(1); DUMPx(pic_info, forward_reference); DUMPx(pic_info, backward_reference); DUMPi(pic_info, slice_count); DUMPi(pic_info, picture_type); DUMPi(pic_info, frame_coding_mode); DUMPi(pic_info, postprocflag); DUMPi(pic_info, pulldown); DUMPi(pic_info, interlace); DUMPi(pic_info, tfcntrflag); DUMPi(pic_info, finterpflag); DUMPi(pic_info, psf); DUMPi(pic_info, dquant); DUMPi(pic_info, panscan_flag); DUMPi(pic_info, refdist_flag); DUMPi(pic_info, quantizer); DUMPi(pic_info, extended_mv); DUMPi(pic_info, extended_dmv); DUMPi(pic_info, overlap); DUMPi(pic_info, vstransform); DUMPi(pic_info, loopfilter); DUMPi(pic_info, fastuvmc); DUMPi(pic_info, range_mapy_flag); DUMPi(pic_info, range_mapy); DUMPi(pic_info, range_mapuv_flag); DUMPi(pic_info, range_mapuv); DUMPi(pic_info, multires); DUMPi(pic_info, syncmarker); DUMPi(pic_info, rangered); DUMPi(pic_info, maxbframes); DUMPi(pic_info, deblockEnable); DUMPi(pic_info, pquant); INDENT(-1); TRACE("};\n"); INDENT(-1); } // Dumps VdpBitstreamBuffer void dump_VdpBitstreamBuffer(VdpBitstreamBuffer *bitstream_buffer) { const uint8_t *buffer = bitstream_buffer->bitstream; const uint32_t size = bitstream_buffer->bitstream_bytes; INDENT(1); TRACE("VdpBitstreamBuffer (%d bytes) = {\n", size); INDENT(1); dump_matrix_NxM("buffer", buffer, 10, 15, size); INDENT(-1); TRACE("};\n"); INDENT(-1); } vdpau-driver-0.7.4/src/vdpau_dump.h000066400000000000000000000036071203356434100172450ustar00rootroot00000000000000/* * vdpau_dump.h - Dump utilities * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_DUMP_H #define VDPAU_DUMP_H #include "vdpau_driver.h" #include "vdpau_decode.h" // Returns string representation of FOURCC const char *string_of_FOURCC(uint32_t fourcc) attribute_hidden; // Returns string representation of VABufferType const char *string_of_VABufferType(VABufferType type) attribute_hidden; // Returns string representation of VdpCodec const char *string_of_VdpCodec(VdpCodec codec) attribute_hidden; // Dumps VdpPictureInfoMPEG1Or2 void dump_VdpPictureInfoMPEG1Or2(VdpPictureInfoMPEG1Or2 *pic_info) attribute_hidden; // Dumps VdpPictureInfoMPEG4Part2 #if HAVE_VDPAU_MPEG4 void dump_VdpPictureInfoMPEG4Part2(VdpPictureInfoMPEG4Part2 *pic_info) attribute_hidden; #endif // Dumps VdpPictureInfoH264 void dump_VdpPictureInfoH264(VdpPictureInfoH264 *pic_info) attribute_hidden; // Dumps VdpPictureInfoVC1 void dump_VdpPictureInfoVC1(VdpPictureInfoVC1 *pic_info) attribute_hidden; // Dumps VdpBitstreamBuffer void dump_VdpBitstreamBuffer(VdpBitstreamBuffer *bitstream_buffer) attribute_hidden; #endif /* VDPAU_DUMP_H */ vdpau-driver-0.7.4/src/vdpau_gate.c000066400000000000000000000667331203356434100172240ustar00rootroot00000000000000/* * vdpau_gate.c - VDPAU hooks * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_gate.h" #include "vdpau_video.h" #define DEBUG 1 #include "debug.h" // Initialize VDPAU hooks int vdpau_gate_init(vdpau_driver_data_t *driver_data) { VdpStatus vdp_status; #define VDP_INIT_PROC(FUNC_ID, FUNC) do { \ vdp_status = driver_data->vdp_get_proc_address \ (driver_data->vdp_device, \ VDP_FUNC_ID_##FUNC_ID, \ (void *)&driver_data->vdp_vtable.vdp_##FUNC); \ if (vdp_status != VDP_STATUS_OK) \ return -1; \ } while (0) VDP_INIT_PROC(DEVICE_DESTROY, device_destroy); VDP_INIT_PROC(GENERATE_CSC_MATRIX, generate_csc_matrix); VDP_INIT_PROC(VIDEO_SURFACE_CREATE, video_surface_create); VDP_INIT_PROC(VIDEO_SURFACE_DESTROY, video_surface_destroy); VDP_INIT_PROC(VIDEO_SURFACE_GET_BITS_Y_CB_CR, video_surface_get_bits_ycbcr); VDP_INIT_PROC(VIDEO_SURFACE_PUT_BITS_Y_CB_CR, video_surface_put_bits_ycbcr); VDP_INIT_PROC(OUTPUT_SURFACE_CREATE, output_surface_create); VDP_INIT_PROC(OUTPUT_SURFACE_DESTROY, output_surface_destroy); VDP_INIT_PROC(OUTPUT_SURFACE_GET_BITS_NATIVE, output_surface_get_bits_native); VDP_INIT_PROC(OUTPUT_SURFACE_PUT_BITS_NATIVE, output_surface_put_bits_native); VDP_INIT_PROC(OUTPUT_SURFACE_RENDER_BITMAP_SURFACE, output_surface_render_bitmap_surface); VDP_INIT_PROC(OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, output_surface_render_output_surface); VDP_INIT_PROC(OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES, output_surface_query_put_bits_indexed_capabilities); VDP_INIT_PROC(OUTPUT_SURFACE_PUT_BITS_INDEXED, output_surface_put_bits_indexed); VDP_INIT_PROC(BITMAP_SURFACE_QUERY_CAPABILITIES, bitmap_surface_query_capabilities); VDP_INIT_PROC(BITMAP_SURFACE_CREATE, bitmap_surface_create); VDP_INIT_PROC(BITMAP_SURFACE_DESTROY, bitmap_surface_destroy); VDP_INIT_PROC(BITMAP_SURFACE_PUT_BITS_NATIVE, bitmap_surface_put_bits_native); VDP_INIT_PROC(VIDEO_MIXER_CREATE, video_mixer_create); VDP_INIT_PROC(VIDEO_MIXER_DESTROY, video_mixer_destroy); VDP_INIT_PROC(VIDEO_MIXER_RENDER, video_mixer_render); VDP_INIT_PROC(VIDEO_MIXER_QUERY_FEATURE_SUPPORT, video_mixer_query_feature_support); VDP_INIT_PROC(VIDEO_MIXER_GET_FEATURE_ENABLES, video_mixer_get_feature_enables); VDP_INIT_PROC(VIDEO_MIXER_SET_FEATURE_ENABLES, video_mixer_set_feature_enables); VDP_INIT_PROC(VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT, video_mixer_query_attribute_support); VDP_INIT_PROC(VIDEO_MIXER_GET_ATTRIBUTE_VALUES, video_mixer_get_attribute_values); VDP_INIT_PROC(VIDEO_MIXER_SET_ATTRIBUTE_VALUES, video_mixer_set_attribute_values); VDP_INIT_PROC(PRESENTATION_QUEUE_CREATE, presentation_queue_create); VDP_INIT_PROC(PRESENTATION_QUEUE_DESTROY, presentation_queue_destroy); VDP_INIT_PROC(PRESENTATION_QUEUE_SET_BACKGROUND_COLOR, presentation_queue_set_background_color); VDP_INIT_PROC(PRESENTATION_QUEUE_GET_BACKGROUND_COLOR, presentation_queue_get_background_color); VDP_INIT_PROC(PRESENTATION_QUEUE_DISPLAY, presentation_queue_display); VDP_INIT_PROC(PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, presentation_queue_block_until_surface_idle); VDP_INIT_PROC(PRESENTATION_QUEUE_QUERY_SURFACE_STATUS, presentation_queue_query_surface_status); VDP_INIT_PROC(PRESENTATION_QUEUE_TARGET_CREATE_X11, presentation_queue_target_create_x11); VDP_INIT_PROC(PRESENTATION_QUEUE_TARGET_DESTROY, presentation_queue_target_destroy); VDP_INIT_PROC(DECODER_CREATE, decoder_create); VDP_INIT_PROC(DECODER_DESTROY, decoder_destroy); VDP_INIT_PROC(DECODER_RENDER, decoder_render); VDP_INIT_PROC(DECODER_QUERY_CAPABILITIES, decoder_query_capabilities); VDP_INIT_PROC(VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, video_surface_query_ycbcr_caps); VDP_INIT_PROC(OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES, output_surface_query_rgba_caps); VDP_INIT_PROC(GET_API_VERSION, get_api_version); VDP_INIT_PROC(GET_INFORMATION_STRING, get_information_string); VDP_INIT_PROC(GET_ERROR_STRING, get_error_string); #undef VDP_INIT_PROC return 0; } // Deinitialize VDPAU hooks void vdpau_gate_exit(vdpau_driver_data_t *driver_data) { } // Check VdpStatus int vdpau_check_status( vdpau_driver_data_p driver_data, VdpStatus vdp_status, const char *msg ) { if (vdp_status != VDP_STATUS_OK) { const char *vdp_status_string; vdp_status_string = vdpau_get_error_string(driver_data, vdp_status); vdpau_information_message("%s: status %d: %s\n", msg, vdp_status, vdp_status_string ? vdp_status_string : ""); return 0; } return 1; } #define VDPAU_INVOKE_(retval, func, ...) \ (driver_data && driver_data->vdp_vtable.vdp_##func \ ? driver_data->vdp_vtable.vdp_##func(__VA_ARGS__) \ : (retval)) #define VDPAU_INVOKE(func, ...) \ VDPAU_INVOKE_(VDP_STATUS_INVALID_POINTER, \ func, __VA_ARGS__) // VdpGenerateCSCMatrix VdpStatus vdpau_generate_csc_matrix( vdpau_driver_data_p driver_data, VdpProcamp *procamp, VdpColorStandard standard, VdpCSCMatrix *csc_matrix ) { return VDPAU_INVOKE(generate_csc_matrix, procamp, standard, csc_matrix); } // VdpDeviceDestroy VdpStatus vdpau_device_destroy( vdpau_driver_data_t *driver_data, VdpDevice device ) { return VDPAU_INVOKE(device_destroy, device); } // VdpVideoSurfaceCreate VdpStatus vdpau_video_surface_create( vdpau_driver_data_t *driver_data, VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height, VdpVideoSurface *surface ) { return VDPAU_INVOKE(video_surface_create, device, chroma_type, width, height, surface); } // VdpVideoSurfaceDestroy VdpStatus vdpau_video_surface_destroy( vdpau_driver_data_t *driver_data, VdpVideoSurface surface ) { return VDPAU_INVOKE(video_surface_destroy, surface); } // VdpVideoSurfaceGetBitsYCbCr VdpStatus vdpau_video_surface_get_bits_ycbcr( vdpau_driver_data_t *driver_data, VdpVideoSurface surface, VdpYCbCrFormat format, uint8_t **dest, uint32_t *stride ) { return VDPAU_INVOKE(video_surface_get_bits_ycbcr, surface, format, (void * const *)dest, stride); } // VdpVideoSurfacePutBitsYCbCr VdpStatus vdpau_video_surface_put_bits_ycbcr( vdpau_driver_data_t *driver_data, VdpVideoSurface surface, VdpYCbCrFormat format, uint8_t **src, uint32_t *stride ) { return VDPAU_INVOKE(video_surface_put_bits_ycbcr, surface, format, (const void * const *)src, stride); } // VdpOutputSurfaceCreate VdpStatus vdpau_output_surface_create( vdpau_driver_data_t *driver_data, VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpOutputSurface *surface ) { return VDPAU_INVOKE(output_surface_create, device, rgba_format, width, height, surface); } // VdpOutputSurfaceDestroy VdpStatus vdpau_output_surface_destroy( vdpau_driver_data_t *driver_data, VdpOutputSurface surface ) { return VDPAU_INVOKE(output_surface_destroy, surface); } // VdpOutputSurfaceGetBitsNative VdpStatus vdpau_output_surface_get_bits_native( vdpau_driver_data_t *driver_data, VdpOutputSurface surface, const VdpRect *source_rect, uint8_t **dst, uint32_t *stride ) { return VDPAU_INVOKE(output_surface_get_bits_native, surface, source_rect, (void * const *)dst, stride); } // VdpOutputSurfacePutBitsNative VdpStatus vdpau_output_surface_put_bits_native( vdpau_driver_data_t *driver_data, VdpOutputSurface surface, const uint8_t **src, uint32_t *stride, const VdpRect *dest_rect ) { return VDPAU_INVOKE(output_surface_put_bits_native, surface, (const void * const *)src, stride, dest_rect); } // VdpOutputSurfaceRenderBitmapSurface VdpStatus vdpau_output_surface_render_bitmap_surface( vdpau_driver_data_t *driver_data, VdpOutputSurface destination_surface, const VdpRect *destination_rect, VdpBitmapSurface source_surface, const VdpRect *source_rect, const VdpColor *colors, const VdpOutputSurfaceRenderBlendState *blend_state, uint32_t flags ) { return VDPAU_INVOKE(output_surface_render_bitmap_surface, destination_surface, destination_rect, source_surface, source_rect, colors, blend_state, flags); } // VdpOutputSurfaceRenderOutputSurface VdpStatus vdpau_output_surface_render_output_surface( vdpau_driver_data_p driver_data, VdpOutputSurface destination_surface, const VdpRect *destination_rect, VdpOutputSurface source_surface, const VdpRect *source_rect, const VdpColor *colors, const VdpOutputSurfaceRenderBlendState *blend_state, uint32_t flags ) { return VDPAU_INVOKE(output_surface_render_output_surface, destination_surface, destination_rect, source_surface, source_rect, colors, blend_state, flags); } // VdpOutputSurfaceQueryPutBitsIndexedCapabilities VdpStatus vdpau_output_surface_query_put_bits_indexed_capabilities( vdpau_driver_data_p driver_data, VdpDevice device, VdpRGBAFormat rgba_format, VdpIndexedFormat bits_indexed_format, VdpColorTableFormat color_table_format, VdpBool *is_supported ) { return VDPAU_INVOKE(output_surface_query_put_bits_indexed_capabilities, device, rgba_format, bits_indexed_format, color_table_format, is_supported); } // VdpOutputSurfacePutBitsIndexed VdpStatus vdpau_output_surface_put_bits_indexed( vdpau_driver_data_p driver_data, VdpOutputSurface surface, VdpIndexedFormat source_indexed_format, const uint8_t **source_data, const uint32_t *source_pitch, const VdpRect *destination_rect, VdpColorTableFormat color_table_format, const void *color_table ) { return VDPAU_INVOKE(output_surface_put_bits_indexed, surface, source_indexed_format, (const void **)source_data, source_pitch, destination_rect, color_table_format, color_table); } // VdpBitmapSurfaceQueryCapabilities VdpStatus vdpau_bitmap_surface_query_capabilities( vdpau_driver_data_t *driver_data, VdpDevice device, VdpRGBAFormat rgba_format, VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height ) { return VDPAU_INVOKE(bitmap_surface_query_capabilities, device, rgba_format, is_supported, max_width, max_height); } // VdpBitmapSurfaceCreate VdpStatus vdpau_bitmap_surface_create( vdpau_driver_data_t *driver_data, VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpBool frequently_accessed, VdpBitmapSurface *surface ) { return VDPAU_INVOKE(bitmap_surface_create, device, rgba_format, width, height, frequently_accessed, surface); } // VdpBitmapSurfaceDestroy VdpStatus vdpau_bitmap_surface_destroy( vdpau_driver_data_t *driver_data, VdpBitmapSurface surface ) { return VDPAU_INVOKE(bitmap_surface_destroy, surface); } // VdpBitmapSurfacePutBitsNative VdpStatus vdpau_bitmap_surface_put_bits_native( vdpau_driver_data_t *driver_data, VdpBitmapSurface surface, const uint8_t **src, const uint32_t *stride, const VdpRect *dest_rect ) { return VDPAU_INVOKE(bitmap_surface_put_bits_native, surface, (const void * const *)src, stride, dest_rect); } // VdpVideoMixerCreate VdpStatus vdpau_video_mixer_create( vdpau_driver_data_t *driver_data, VdpDevice device, uint32_t feature_count, VdpVideoMixerFeature const *features, uint32_t parameter_count, VdpVideoMixerParameter const *parameters, const void *parameter_values, VdpVideoMixer *mixer ) { return VDPAU_INVOKE(video_mixer_create, device, feature_count, features, parameter_count, parameters, parameter_values, mixer); } // VdpVideoMixerDestroy VdpStatus vdpau_video_mixer_destroy( vdpau_driver_data_t *driver_data, VdpVideoMixer mixer ) { return VDPAU_INVOKE(video_mixer_destroy, mixer); } // VdpVideoMixerRender VdpStatus vdpau_video_mixer_render( vdpau_driver_data_t *driver_data, VdpVideoMixer mixer, VdpOutputSurface background_surface, const VdpRect *background_source_rect, VdpVideoMixerPictureStructure current_picture_structure, uint32_t video_surface_past_count, const VdpVideoSurface *video_surface_past, VdpVideoSurface video_surface_current, uint32_t video_surface_future_count, const VdpVideoSurface *video_surface_future, const VdpRect *video_source_rect, VdpOutputSurface destination_surface, const VdpRect *destination_rect, const VdpRect *destination_video_rect, uint32_t layer_count, const VdpLayer *layers ) { return VDPAU_INVOKE(video_mixer_render, mixer, background_surface, background_source_rect, current_picture_structure, video_surface_past_count, video_surface_past, video_surface_current, video_surface_future_count, video_surface_future, video_source_rect, destination_surface, destination_rect, destination_video_rect, layer_count, layers); } // VdpVideoMixerQueryFeatureSupport VdpStatus vdpau_video_mixer_query_feature_support( vdpau_driver_data_p driver_data, VdpDevice device, VdpVideoMixerFeature feature, VdpBool *is_supported ) { return VDPAU_INVOKE(video_mixer_query_feature_support, device, feature, is_supported); } // VdpVideoMixerGetFeatureEnables VdpStatus vdpau_video_mixer_get_feature_enables( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t feature_count, const VdpVideoMixerFeature *features, VdpBool *feature_enables ) { return VDPAU_INVOKE(video_mixer_get_feature_enables, mixer, feature_count, features, feature_enables); } // VdpVideoMixerSetFeatureEnables VdpStatus vdpau_video_mixer_set_feature_enables( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t feature_count, const VdpVideoMixerFeature *features, const VdpBool *feature_enables ) { return VDPAU_INVOKE(video_mixer_set_feature_enables, mixer, feature_count, features, feature_enables); } // VdpVideoMixerQueryAttributeSupport VdpStatus vdpau_video_mixer_query_attribute_support( vdpau_driver_data_p driver_data, VdpDevice device, VdpVideoMixerAttribute attribute, VdpBool *is_supported ) { return VDPAU_INVOKE(video_mixer_query_attribute_support, device, attribute, is_supported); } // VdpVideoMixerGetAttributeValues VdpStatus vdpau_video_mixer_get_attribute_values( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t attribute_count, const VdpVideoMixerAttribute *attributes, void **attribute_values ) { return VDPAU_INVOKE(video_mixer_get_attribute_values, mixer, attribute_count, attributes, attribute_values); } // VdpVideoMixerSetAttributeValues VdpStatus vdpau_video_mixer_set_attribute_values( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t attribute_count, const VdpVideoMixerAttribute *attributes, const void **attribute_values ) { return VDPAU_INVOKE(video_mixer_set_attribute_values, mixer, attribute_count, attributes, attribute_values); } // VdpPresentationQueueCreate VdpStatus vdpau_presentation_queue_create( vdpau_driver_data_t *driver_data, VdpDevice device, VdpPresentationQueueTarget presentation_queue_target, VdpPresentationQueue *presentation_queue ) { return VDPAU_INVOKE(presentation_queue_create, device, presentation_queue_target, presentation_queue); } // VdpPresentationQueueDestroy VdpStatus vdpau_presentation_queue_destroy( vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue ) { return VDPAU_INVOKE(presentation_queue_destroy, presentation_queue); } // VdpPresentationQueueSetBackgroundColor VdpStatus vdpau_presentation_queue_set_background_color( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, const VdpColor *background_color ) { return VDPAU_INVOKE(presentation_queue_set_background_color, presentation_queue, (VdpColor *)background_color); } //VdpPresentationQueueGetBackgroundColor VdpStatus vdpau_presentation_queue_get_background_color( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, VdpColor *background_color ) { return VDPAU_INVOKE(presentation_queue_get_background_color, presentation_queue, background_color); } // VdpPresentationQueueDisplay VdpStatus vdpau_presentation_queue_display( vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, uint32_t clip_width, uint32_t clip_height, VdpTime earliest_presentation_time ) { return VDPAU_INVOKE(presentation_queue_display, presentation_queue, surface, clip_width, clip_height, earliest_presentation_time); } // VdpPresentationQueueBlockUntilSurfaceIdle VdpStatus vdpau_presentation_queue_block_until_surface_idle( vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, VdpTime *first_presentation_time ) { return VDPAU_INVOKE(presentation_queue_block_until_surface_idle, presentation_queue, surface, first_presentation_time); } // VdpPresentationQueueQuerySurfaceStatus VdpStatus vdpau_presentation_queue_query_surface_status( vdpau_driver_data_t *driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, VdpPresentationQueueStatus *status, VdpTime *first_presentation_time ) { return VDPAU_INVOKE(presentation_queue_query_surface_status, presentation_queue, surface, status, first_presentation_time); } // VdpPresentationQueueTargetCreateX11 VdpStatus vdpau_presentation_queue_target_create_x11( vdpau_driver_data_t *driver_data, VdpDevice device, Drawable drawable, VdpPresentationQueueTarget *target ) { return VDPAU_INVOKE(presentation_queue_target_create_x11, device, drawable, target); } // VdpPresentationQueueTargetDestroy VdpStatus vdpau_presentation_queue_target_destroy( vdpau_driver_data_t *driver_data, VdpPresentationQueueTarget presentation_queue_target ) { return VDPAU_INVOKE(presentation_queue_target_destroy, presentation_queue_target); } // VdpDecoderCreate VdpStatus vdpau_decoder_create( vdpau_driver_data_t *driver_data, VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder ) { return VDPAU_INVOKE(decoder_create, device, profile, width, height, max_references, decoder); } // VdpDecoderDestroy VdpStatus vdpau_decoder_destroy( vdpau_driver_data_t *driver_data, VdpDecoder decoder ) { return VDPAU_INVOKE(decoder_destroy, decoder); } // VdpDecoderRender VdpStatus vdpau_decoder_render( vdpau_driver_data_t *driver_data, VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffers_count, VdpBitstreamBuffer const *bitstream_buffers ) { return VDPAU_INVOKE(decoder_render, decoder, target, picture_info, bitstream_buffers_count, bitstream_buffers); } // VdpDecoderQueryCapabilities VdpStatus vdpau_decoder_query_capabilities( vdpau_driver_data_t *driver_data, VdpDevice device, VdpDecoderProfile profile, VdpBool *is_supported, uint32_t *max_level, uint32_t *max_references, uint32_t *max_width, uint32_t *max_height ) { return VDPAU_INVOKE(decoder_query_capabilities, device, profile, is_supported, max_level, max_references, max_width, max_height); } // VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities VdpStatus vdpau_video_surface_query_ycbcr_caps( vdpau_driver_data_t *driver_data, VdpDevice device, VdpChromaType surface_chroma_type, VdpYCbCrFormat bits_ycbcr_format, VdpBool *is_supported ) { return VDPAU_INVOKE(video_surface_query_ycbcr_caps, device, surface_chroma_type, bits_ycbcr_format, is_supported); } // VdpOutputSurfaceQueryGetPutBitsNativeCapabilities VdpStatus vdpau_output_surface_query_rgba_caps( vdpau_driver_data_t *driver_data, VdpDevice device, VdpRGBAFormat surface_rgba_format, VdpBool *is_supported ) { return VDPAU_INVOKE(output_surface_query_rgba_caps, device, surface_rgba_format, is_supported); } // VdpGetApiVersion VdpStatus vdpau_get_api_version(vdpau_driver_data_t *driver_data, uint32_t *api_version) { return VDPAU_INVOKE(get_api_version, api_version); } // VdpGetInformationString VdpStatus vdpau_get_information_string( vdpau_driver_data_t *driver_data, const char **info_string ) { return VDPAU_INVOKE(get_information_string, info_string); } // VdpGetErrorString const char * vdpau_get_error_string(vdpau_driver_data_t *driver_data, VdpStatus vdp_status) { return VDPAU_INVOKE_(NULL, get_error_string, vdp_status); } vdpau-driver-0.7.4/src/vdpau_gate.h000066400000000000000000000434521203356434100172220ustar00rootroot00000000000000/* * vdpau_gate.h - VDPAU hooks * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_GATE_H #define VDPAU_GATE_H #include #include typedef struct vdpau_vtable vdpau_vtable_t; typedef struct vdpau_vtable *vdpau_vtable_p; typedef struct vdpau_driver_data *vdpau_driver_data_p; // VDPAU VTable struct vdpau_vtable { VdpDeviceDestroy *vdp_device_destroy; VdpGenerateCSCMatrix *vdp_generate_csc_matrix; VdpVideoSurfaceCreate *vdp_video_surface_create; VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_ycbcr; VdpOutputSurfaceCreate *vdp_output_surface_create; VdpOutputSurfaceDestroy *vdp_output_surface_destroy; VdpOutputSurfaceGetBitsNative *vdp_output_surface_get_bits_native; VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits_native; VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; VdpOutputSurfaceQueryPutBitsIndexedCapabilities *vdp_output_surface_query_put_bits_indexed_capabilities; VdpOutputSurfacePutBitsIndexed *vdp_output_surface_put_bits_indexed; VdpBitmapSurfaceQueryCapabilities *vdp_bitmap_surface_query_capabilities; VdpBitmapSurfaceCreate *vdp_bitmap_surface_create; VdpBitmapSurfaceDestroy *vdp_bitmap_surface_destroy; VdpBitmapSurfacePutBitsNative *vdp_bitmap_surface_put_bits_native; VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy; VdpVideoMixerRender *vdp_video_mixer_render; VdpVideoMixerQueryFeatureSupport *vdp_video_mixer_query_feature_support; VdpVideoMixerGetFeatureEnables *vdp_video_mixer_get_feature_enables; VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; VdpVideoMixerQueryAttributeSupport *vdp_video_mixer_query_attribute_support; VdpVideoMixerGetAttributeValues *vdp_video_mixer_get_attribute_values; VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; VdpPresentationQueueCreate *vdp_presentation_queue_create; VdpPresentationQueueDestroy *vdp_presentation_queue_destroy; VdpPresentationQueueSetBackgroundColor *vdp_presentation_queue_set_background_color; VdpPresentationQueueGetBackgroundColor *vdp_presentation_queue_get_background_color; VdpPresentationQueueDisplay *vdp_presentation_queue_display; VdpPresentationQueueBlockUntilSurfaceIdle *vdp_presentation_queue_block_until_surface_idle; VdpPresentationQueueQuerySurfaceStatus *vdp_presentation_queue_query_surface_status; VdpPresentationQueueTargetCreateX11 *vdp_presentation_queue_target_create_x11; VdpPresentationQueueTargetDestroy *vdp_presentation_queue_target_destroy; VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_caps; VdpOutputSurfaceQueryGetPutBitsNativeCapabilities *vdp_output_surface_query_rgba_caps; VdpGetApiVersion *vdp_get_api_version; VdpGetInformationString *vdp_get_information_string; VdpGetErrorString *vdp_get_error_string; }; // Initialize VDPAU hooks int vdpau_gate_init(vdpau_driver_data_p driver_data) attribute_hidden; // Deinitialize VDPAU hooks void vdpau_gate_exit(vdpau_driver_data_p driver_data) attribute_hidden; // Check VdpStatus int vdpau_check_status( vdpau_driver_data_p driver_data, VdpStatus vdp_status, const char *msg ) attribute_hidden; #define VDPAU_CHECK_STATUS(status, msg) \ vdpau_check_status(driver_data, status, msg) // VdpGetApiVersion VdpStatus vdpau_get_api_version(vdpau_driver_data_p driver_data, uint32_t *api_version) attribute_hidden; // VdpGetInformationString VdpStatus vdpau_get_information_string( vdpau_driver_data_p driver_data, const char **info_string ) attribute_hidden; // VdpGetErrorString const char * vdpau_get_error_string(vdpau_driver_data_p driver_data, VdpStatus vdp_status) attribute_hidden; // VdpGenerateCSCMatrix VdpStatus vdpau_generate_csc_matrix( vdpau_driver_data_p driver_data, VdpProcamp *procamp, VdpColorStandard standard, VdpCSCMatrix *csc_matrix ) attribute_hidden; // VdpDeviceDestroy VdpStatus vdpau_device_destroy( vdpau_driver_data_p driver_data, VdpDevice device ) attribute_hidden; // VdpVideoSurfaceCreate VdpStatus vdpau_video_surface_create( vdpau_driver_data_p driver_data, VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height, VdpVideoSurface *surface ) attribute_hidden; // VdpVideoSurfaceDestroy VdpStatus vdpau_video_surface_destroy( vdpau_driver_data_p driver_data, VdpVideoSurface surface ) attribute_hidden; // VdpVideoSurfaceGetBitsYCbCr VdpStatus vdpau_video_surface_get_bits_ycbcr( vdpau_driver_data_p driver_data, VdpVideoSurface surface, VdpYCbCrFormat format, uint8_t **dest, uint32_t *stride ) attribute_hidden; // VdpVideoSurfacePutBitsYCbCr VdpStatus vdpau_video_surface_put_bits_ycbcr( vdpau_driver_data_p driver_data, VdpVideoSurface surface, VdpYCbCrFormat format, uint8_t **src, uint32_t *stride ) attribute_hidden; // VdpOutputSurfaceCreate VdpStatus vdpau_output_surface_create( vdpau_driver_data_p driver_data, VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpOutputSurface *surface ) attribute_hidden; // VdpOutputSurfaceDestroy VdpStatus vdpau_output_surface_destroy( vdpau_driver_data_p driver_data, VdpOutputSurface surface ) attribute_hidden; // VdpOutputSurfaceGetBitsNative VdpStatus vdpau_output_surface_get_bits_native( vdpau_driver_data_p driver_data, VdpOutputSurface surface, const VdpRect *source_rect, uint8_t **dst, uint32_t *stride ) attribute_hidden; // VdpOutputSurfacePutBitsNative VdpStatus vdpau_output_surface_put_bits_native( vdpau_driver_data_p driver_data, VdpOutputSurface surface, const uint8_t **src, uint32_t *stride, const VdpRect *dest_rect ) attribute_hidden; // VdpOutputSurfaceRenderBitmapSurface VdpStatus vdpau_output_surface_render_bitmap_surface( vdpau_driver_data_p driver_data, VdpOutputSurface destination_surface, const VdpRect *destination_rect, VdpBitmapSurface source_surface, const VdpRect *source_rect, const VdpColor *colors, const VdpOutputSurfaceRenderBlendState *blend_state, uint32_t flags ) attribute_hidden; // VdpOutputSurfaceRenderOutputSurface VdpStatus vdpau_output_surface_render_output_surface( vdpau_driver_data_p driver_data, VdpOutputSurface destination_surface, const VdpRect *destination_rect, VdpOutputSurface source_surface, const VdpRect *source_rect, const VdpColor *colors, const VdpOutputSurfaceRenderBlendState *blend_state, uint32_t flags ) attribute_hidden; // VdpOutputSurfaceQueryPutBitsIndexedCapabilities VdpStatus vdpau_output_surface_query_put_bits_indexed_capabilities( vdpau_driver_data_p driver_data, VdpDevice device, VdpRGBAFormat rgba_format, VdpIndexedFormat bits_indexed_format, VdpColorTableFormat color_table_format, VdpBool *is_supported ) attribute_hidden; // VdpOutputSurfacePutBitsIndexed VdpStatus vdpau_output_surface_put_bits_indexed( vdpau_driver_data_p driver_data, VdpOutputSurface surface, VdpIndexedFormat source_indexed_format, const uint8_t **source_data, const uint32_t *source_pitch, const VdpRect *destination_rect, VdpColorTableFormat color_table_format, const void *color_table ) attribute_hidden; // VdpBitmapSurfaceQueryCapabilities VdpStatus vdpau_bitmap_surface_query_capabilities( vdpau_driver_data_p driver_data, VdpDevice device, VdpRGBAFormat rgba_format, VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height ) attribute_hidden; // VdpBitmapSurfaceCreate VdpStatus vdpau_bitmap_surface_create( vdpau_driver_data_p driver_data, VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpBool frequently_accessed, VdpBitmapSurface *surface ) attribute_hidden; // VdpBitmapSurfaceDestroy VdpStatus vdpau_bitmap_surface_destroy( vdpau_driver_data_p driver_data, VdpBitmapSurface surface ) attribute_hidden; // VdpBitmapSurfacePutBitsNative VdpStatus vdpau_bitmap_surface_put_bits_native( vdpau_driver_data_p driver_data, VdpBitmapSurface surface, const uint8_t **src, const uint32_t *stride, const VdpRect *dest_rect ) attribute_hidden; // VdpVideoMixerCreate VdpStatus vdpau_video_mixer_create( vdpau_driver_data_p driver_data, VdpDevice device, uint32_t feature_count, VdpVideoMixerFeature const *features, uint32_t parameter_count, VdpVideoMixerParameter const *parameters, const void *parameter_values, VdpVideoMixer *mixer ) attribute_hidden; // VdpVideoMixerDestroy VdpStatus vdpau_video_mixer_destroy( vdpau_driver_data_p driver_data, VdpVideoMixer mixer ) attribute_hidden; // VdpVideoMixerRender VdpStatus vdpau_video_mixer_render( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, VdpOutputSurface background_surface, const VdpRect *background_source_rect, VdpVideoMixerPictureStructure current_picture_structure, uint32_t video_surface_past_count, const VdpVideoSurface *video_surface_past, VdpVideoSurface video_surface_current, uint32_t video_surface_future_count, const VdpVideoSurface *video_surface_future, const VdpRect *video_source_rect, VdpOutputSurface destination_surface, const VdpRect *destination_rect, const VdpRect *destination_video_rect, uint32_t layer_count, const VdpLayer *layers ) attribute_hidden; // VdpVideoMixerQueryFeatureSupport VdpStatus vdpau_video_mixer_query_feature_support( vdpau_driver_data_p driver_data, VdpDevice device, VdpVideoMixerFeature feature, VdpBool *is_supported ) attribute_hidden; // VdpVideoMixerGetFeatureEnables VdpStatus vdpau_video_mixer_get_feature_enables( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t feature_count, const VdpVideoMixerFeature *features, VdpBool *feature_enables ) attribute_hidden; // VdpVideoMixerSetFeatureEnables VdpStatus vdpau_video_mixer_set_feature_enables( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t feature_count, const VdpVideoMixerFeature *features, const VdpBool *feature_enables ) attribute_hidden; // VdpVideoMixerQueryAttributeSupport VdpStatus vdpau_video_mixer_query_attribute_support( vdpau_driver_data_p driver_data, VdpDevice device, VdpVideoMixerAttribute attribute, VdpBool *is_supported ) attribute_hidden; // VdpVideoMixerGetAttributeValues VdpStatus vdpau_video_mixer_get_attribute_values( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t attribute_count, const VdpVideoMixerAttribute *attributes, void **attribute_values ) attribute_hidden; // VdpVideoMixerSetAttributeValues VdpStatus vdpau_video_mixer_set_attribute_values( vdpau_driver_data_p driver_data, VdpVideoMixer mixer, uint32_t attribute_count, const VdpVideoMixerAttribute *attributes, const void **attribute_values ) attribute_hidden; // VdpPresentationQueueCreate VdpStatus vdpau_presentation_queue_create( vdpau_driver_data_p driver_data, VdpDevice device, VdpPresentationQueueTarget presentation_queue_target, VdpPresentationQueue *presentation_queue ) attribute_hidden; // VdpPresentationQueueDestroy VdpStatus vdpau_presentation_queue_destroy( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue ) attribute_hidden; // VdpPresentationQueueSetBackgroundColor VdpStatus vdpau_presentation_queue_set_background_color( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, const VdpColor *background_color ) attribute_hidden; //VdpPresentationQueueGetBackgroundColor VdpStatus vdpau_presentation_queue_get_background_color( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, VdpColor *background_color ) attribute_hidden; // VdpPresentationQueueDisplay VdpStatus vdpau_presentation_queue_display( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, uint32_t clip_width, uint32_t clip_height, VdpTime earliest_presentation_time ) attribute_hidden; // VdpPresentationQueueBlockUntilSurfaceIdle VdpStatus vdpau_presentation_queue_block_until_surface_idle( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, VdpTime *first_presentation_time ) attribute_hidden; // VdpPresentationQueueQuerySurfaceStatus VdpStatus vdpau_presentation_queue_query_surface_status( vdpau_driver_data_p driver_data, VdpPresentationQueue presentation_queue, VdpOutputSurface surface, VdpPresentationQueueStatus *status, VdpTime *first_presentation_time ) attribute_hidden; // VdpPresentationQueueTargetCreateX11 VdpStatus vdpau_presentation_queue_target_create_x11( vdpau_driver_data_p driver_data, VdpDevice device, Drawable drawable, VdpPresentationQueueTarget *target ) attribute_hidden; // VdpPresentationQueueTargetDestroy VdpStatus vdpau_presentation_queue_target_destroy( vdpau_driver_data_p driver_data, VdpPresentationQueueTarget presentation_queue_target ) attribute_hidden; // VdpDecoderCreate VdpStatus vdpau_decoder_create( vdpau_driver_data_p driver_data, VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder ) attribute_hidden; // VdpDecoderDestroy VdpStatus vdpau_decoder_destroy( vdpau_driver_data_p driver_data, VdpDecoder decoder ) attribute_hidden; // VdpDecoderRender VdpStatus vdpau_decoder_render( vdpau_driver_data_p driver_data, VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffers_count, VdpBitstreamBuffer const *bitstream_buffers ) attribute_hidden; // VdpDecoderQueryCapabilities VdpStatus vdpau_decoder_query_capabilities( vdpau_driver_data_p driver_data, VdpDevice device, VdpDecoderProfile profile, VdpBool *is_supported, uint32_t *max_level, uint32_t *max_references, uint32_t *max_width, uint32_t *max_height ) attribute_hidden; // VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities VdpStatus vdpau_video_surface_query_ycbcr_caps( vdpau_driver_data_p driver_data, VdpDevice device, VdpChromaType surface_chroma_type, VdpYCbCrFormat bits_ycbcr_format, VdpBool *is_supported ) attribute_hidden; // VdpOutputSurfaceQueryGetPutBitsNativeCapabilities VdpStatus vdpau_output_surface_query_rgba_caps( vdpau_driver_data_p driver_data, VdpDevice device, VdpRGBAFormat surface_rgba_format, VdpBool *is_supported ) attribute_hidden; #endif /* VDPAU_GATE_H */ vdpau-driver-0.7.4/src/vdpau_image.c000066400000000000000000000512211203356434100173500ustar00rootroot00000000000000/* * vdpau_image.c - VDPAU backend for VA-API (VA images) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_image.h" #include "vdpau_video.h" #include "vdpau_buffer.h" #include "vdpau_mixer.h" #define DEBUG 1 #include "debug.h" // List of supported image formats typedef struct { VdpImageFormatType vdp_format_type; uint32_t vdp_format; VAImageFormat va_format; unsigned int num_palette_entries; unsigned int entry_bytes; char component_order[4]; } vdpau_image_format_map_t; static const vdpau_image_format_map_t vdpau_image_formats_map[] = { #define DEF(TYPE, FORMAT) \ VDP_IMAGE_FORMAT_TYPE_##TYPE, VDP_##TYPE##_FORMAT_##FORMAT #define DEF_YUV(TYPE, FORMAT, FOURCC, ENDIAN, BPP) \ { DEF(TYPE, FORMAT), { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, }, } #define DEF_RGB(TYPE, FORMAT, FOURCC, ENDIAN, BPP, DEPTH, R,G,B,A) \ { DEF(TYPE, FORMAT), { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, DEPTH, R,G,B,A }, } #define DEF_IDX(TYPE, FORMAT, FOURCC, ENDIAN, BPP, NPE, EB, C0,C1,C2,C3) \ { DEF(TYPE, FORMAT), { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, }, \ NPE, EB, { C0, C1, C2, C3 } } DEF_YUV(YCBCR, NV12, ('N','V','1','2'), LSB, 12), DEF_YUV(YCBCR, YV12, ('Y','V','1','2'), LSB, 12), DEF_YUV(YCBCR, YV12, ('I','4','2','0'), LSB, 12), // swap U/V planes DEF_YUV(YCBCR, UYVY, ('U','Y','V','Y'), LSB, 16), DEF_YUV(YCBCR, YUYV, ('Y','U','Y','V'), LSB, 16), DEF_YUV(YCBCR, V8U8Y8A8, ('A','Y','U','V'), LSB, 32), #ifdef WORDS_BIGENDIAN DEF_RGB(RGBA, B8G8R8A8, ('A','R','G','B'), MSB, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), DEF_RGB(RGBA, R8G8B8A8, ('A','B','G','R'), MSB, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000), #else DEF_RGB(RGBA, B8G8R8A8, ('B','G','R','A'), LSB, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), DEF_RGB(RGBA, R8G8B8A8, ('R','G','B','A'), LSB, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000), #endif DEF_IDX(INDEXED, A4I4, ('A','I','4','4'), MSB, 8, 16, 3, 'R','G','B',0), DEF_IDX(INDEXED, I4A4, ('I','A','4','4'), MSB, 8, 16, 3, 'R','G','B',0), DEF_IDX(INDEXED, A8I8, ('A','I','8','8'), MSB, 16, 256, 3, 'R','G','B',0), DEF_IDX(INDEXED, I8A8, ('I','A','8','8'), MSB, 16, 256, 3, 'R','G','B',0), #undef DEF_IDX #undef DEF_RGB #undef DEF_YUV #undef DEF }; // Returns a suitable VDPAU image format for the specified VA image format static const vdpau_image_format_map_t *get_format(const VAImageFormat *format) { unsigned int i; for (i = 0; i < ARRAY_ELEMS(vdpau_image_formats_map); i++) { const vdpau_image_format_map_t * const m = &vdpau_image_formats_map[i]; if (m->va_format.fourcc == format->fourcc && (m->vdp_format_type == VDP_IMAGE_FORMAT_TYPE_RGBA ? (m->va_format.byte_order == format->byte_order && m->va_format.red_mask == format->red_mask && m->va_format.green_mask == format->green_mask && m->va_format.blue_mask == format->blue_mask && m->va_format.alpha_mask == format->alpha_mask) : 1)) return m; } return NULL; } // Checks whether the VDPAU implementation supports the specified image format static inline VdpBool is_supported_format( vdpau_driver_data_t *driver_data, VdpImageFormatType type, uint32_t format ) { VdpBool is_supported = VDP_FALSE; VdpStatus vdp_status; switch (type) { case VDP_IMAGE_FORMAT_TYPE_YCBCR: vdp_status = vdpau_video_surface_query_ycbcr_caps(driver_data, driver_data->vdp_device, VDP_CHROMA_TYPE_420, format, &is_supported); break; case VDP_IMAGE_FORMAT_TYPE_RGBA: vdp_status = vdpau_output_surface_query_rgba_caps(driver_data, driver_data->vdp_device, format, &is_supported); break; default: vdp_status = VDP_STATUS_INVALID_VALUE; break; } return vdp_status == VDP_STATUS_OK && is_supported; } // vaQueryImageFormats VAStatus vdpau_QueryImageFormats( VADriverContextP ctx, VAImageFormat *format_list, int *num_formats ) { VDPAU_DRIVER_DATA_INIT; if (num_formats) *num_formats = 0; if (format_list == NULL) return VA_STATUS_SUCCESS; int i, n = 0; for (i = 0; i < ARRAY_ELEMS(vdpau_image_formats_map); i++) { const vdpau_image_format_map_t * const f = &vdpau_image_formats_map[i]; if (is_supported_format(driver_data, f->vdp_format_type, f->vdp_format)) format_list[n++] = f->va_format; } /* If the assert fails then VDPAU_MAX_IMAGE_FORMATS needs to be bigger */ ASSERT(n <= VDPAU_MAX_IMAGE_FORMATS); if (num_formats) *num_formats = n; return VA_STATUS_SUCCESS; } // vaCreateImage VAStatus vdpau_CreateImage( VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *out_image ) { VDPAU_DRIVER_DATA_INIT; VAStatus va_status = VA_STATUS_ERROR_OPERATION_FAILED; unsigned int i, width2, height2, size2, size; if (!format || !out_image) return VA_STATUS_ERROR_INVALID_PARAMETER; out_image->image_id = VA_INVALID_ID; out_image->buf = VA_INVALID_ID; VAImageID image_id = object_heap_allocate(&driver_data->image_heap); if (image_id == VA_INVALID_ID) { va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; goto error; } object_image_p obj_image = VDPAU_IMAGE(image_id); if (!obj_image) { va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; goto error; } const vdpau_image_format_map_t *m = get_format(format); if (!m) { va_status = VA_STATUS_ERROR_UNKNOWN; /* VA_STATUS_ERROR_UNSUPPORTED_FORMAT */ goto error; } VAImage * const image = &obj_image->image; image->image_id = image_id; image->buf = VA_INVALID_ID; size = width * height; width2 = (width + 1) / 2; height2 = (height + 1) / 2; size2 = width2 * height2; switch (format->fourcc) { case VA_FOURCC('N','V','1','2'): image->num_planes = 2; image->pitches[0] = width; image->offsets[0] = 0; image->pitches[1] = width; image->offsets[1] = size; image->data_size = size + 2 * size2; break; case VA_FOURCC('Y','V','1','2'): case VA_FOURCC('I','4','2','0'): image->num_planes = 3; image->pitches[0] = width; image->offsets[0] = 0; image->pitches[1] = width2; image->offsets[1] = size; image->pitches[2] = width2; image->offsets[2] = size + size2; image->data_size = size + 2 * size2; break; case VA_FOURCC('A','R','G','B'): case VA_FOURCC('A','B','G','R'): case VA_FOURCC('B','G','R','A'): case VA_FOURCC('R','G','B','A'): case VA_FOURCC('U','Y','V','Y'): case VA_FOURCC('Y','U','Y','V'): image->num_planes = 1; image->pitches[0] = width * 4; image->offsets[0] = 0; image->data_size = image->offsets[0] + image->pitches[0] * height; break; case VA_FOURCC('I','A','4','4'): case VA_FOURCC('A','I','4','4'): image->num_planes = 1; image->pitches[0] = width; image->offsets[0] = 0; image->data_size = image->offsets[0] + image->pitches[0] * height; break; case VA_FOURCC('I','A','8','8'): case VA_FOURCC('A','I','8','8'): image->num_planes = 1; image->pitches[0] = width * 2; image->offsets[0] = 0; image->data_size = image->offsets[0] + image->pitches[0] * height; break; default: goto error; } /* Allocate more bytes to align image data base on 16-byte boundaries */ /* XXX: align other planes too? */ static const int ALIGN = 16; va_status = vdpau_CreateBuffer(ctx, 0, VAImageBufferType, image->data_size + ALIGN, 1, NULL, &image->buf); if (va_status != VA_STATUS_SUCCESS) goto error; object_buffer_p obj_buffer = VDPAU_BUFFER(image->buf); if (!obj_buffer) goto error; int align = ((uintptr_t)obj_buffer->buffer_data) % ALIGN; if (align) { align = ALIGN - align; for (i = 0; i < image->num_planes; i++) image->offsets[i] += align; } obj_image->vdp_rgba_output_surface = VDP_INVALID_HANDLE; obj_image->vdp_format_type = m->vdp_format_type; obj_image->vdp_format = m->vdp_format; obj_image->vdp_palette = NULL; image->image_id = image_id; image->format = *format; image->width = width; image->height = height; image->num_palette_entries = m->num_palette_entries; image->entry_bytes = m->entry_bytes; for (i = 0; i < image->entry_bytes; i++) image->component_order[i] = m->component_order[i]; for (; i < 4; i++) image->component_order[i] = 0; *out_image = *image; return VA_STATUS_SUCCESS; error: vdpau_DestroyImage(ctx, image_id); return va_status; } // vaDestroyImage VAStatus vdpau_DestroyImage( VADriverContextP ctx, VAImageID image_id ) { VDPAU_DRIVER_DATA_INIT; object_image_p obj_image = VDPAU_IMAGE(image_id); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; if (obj_image->vdp_rgba_output_surface != VDP_INVALID_HANDLE) vdpau_output_surface_destroy(driver_data, obj_image->vdp_rgba_output_surface); if (obj_image->vdp_palette) { free(obj_image->vdp_palette); obj_image->vdp_palette = NULL; } VABufferID buf = obj_image->image.buf; object_heap_free(&driver_data->image_heap, (object_base_p)obj_image); return vdpau_DestroyBuffer(ctx, buf); } // vaDeriveImage VAStatus vdpau_DeriveImage( VADriverContextP ctx, VASurfaceID surface, VAImage *image ) { /* TODO */ return VA_STATUS_ERROR_OPERATION_FAILED; } // Set image palette static VAStatus set_image_palette( vdpau_driver_data_t *driver_data, object_image_p obj_image, const unsigned char *palette ) { if (obj_image->vdp_format_type != VDP_IMAGE_FORMAT_TYPE_INDEXED) return VA_STATUS_ERROR_OPERATION_FAILED; if (!obj_image->vdp_palette) { obj_image->vdp_palette = malloc(4 * obj_image->image.num_palette_entries); if (!obj_image->vdp_palette) return VA_STATUS_ERROR_ALLOCATION_FAILED; } unsigned int i; for (i = 0; i < obj_image->image.num_palette_entries; i++) { /* B8G8R8X8 format */ obj_image->vdp_palette[i] = ((palette[3*i + 0] << 16) | (palette[3*i + 1] << 8) | palette[3*i + 2]); } return VA_STATUS_SUCCESS; } // vaSetImagePalette VAStatus vdpau_SetImagePalette( VADriverContextP ctx, VAImageID image, unsigned char *palette ) { VDPAU_DRIVER_DATA_INIT; object_image_p obj_image = VDPAU_IMAGE(image); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; return set_image_palette(driver_data, obj_image, palette); } // Get image from surface static VAStatus get_image( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_image_p obj_image, const VARectangle *rect ) { VAImage * const image = &obj_image->image; VdpStatus vdp_status; uint8_t *src[3]; unsigned int src_stride[3]; int i; object_buffer_p obj_buffer = VDPAU_BUFFER(image->buf); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; switch (image->format.fourcc) { case VA_FOURCC('I','4','2','0'): src[0] = (uint8_t *)obj_buffer->buffer_data + image->offsets[0]; src_stride[0] = image->pitches[0]; src[1] = (uint8_t *)obj_buffer->buffer_data + image->offsets[2]; src_stride[1] = image->pitches[2]; src[2] = (uint8_t *)obj_buffer->buffer_data + image->offsets[1]; src_stride[2] = image->pitches[1]; break; default: for (i = 0; i < image->num_planes; i++) { src[i] = (uint8_t *)obj_buffer->buffer_data + image->offsets[i]; src_stride[i] = image->pitches[i]; } break; } switch (obj_image->vdp_format_type) { case VDP_IMAGE_FORMAT_TYPE_YCBCR: { /* VDPAU only supports full video surface readback */ if (rect->x != 0 || rect->y != 0 || obj_surface->width != rect->width || obj_surface->height != rect->height) return VA_STATUS_ERROR_OPERATION_FAILED; vdp_status = vdpau_video_surface_get_bits_ycbcr( driver_data, obj_surface->vdp_surface, obj_image->vdp_format, src, src_stride ); break; } case VDP_IMAGE_FORMAT_TYPE_RGBA: { if (obj_image->vdp_rgba_output_surface == VA_INVALID_ID) { vdp_status = vdpau_output_surface_create( driver_data, driver_data->vdp_device, obj_image->vdp_format, obj_image->image.width, obj_image->image.height, &obj_image->vdp_rgba_output_surface ); if (vdp_status != VDP_STATUS_OK) return vdpau_get_VAStatus(vdp_status); } VdpRect vdp_rect; vdp_rect.x0 = rect->x; vdp_rect.y0 = rect->y; vdp_rect.x1 = rect->x + rect->width; vdp_rect.y1 = rect->y + rect->height; vdp_status = video_mixer_render( driver_data, obj_surface->video_mixer, obj_surface, VDP_INVALID_HANDLE, obj_image->vdp_rgba_output_surface, &vdp_rect, &vdp_rect, 0 ); if (vdp_status != VDP_STATUS_OK) return vdpau_get_VAStatus(vdp_status); vdp_status = vdpau_output_surface_get_bits_native( driver_data, obj_image->vdp_rgba_output_surface, &vdp_rect, src, src_stride ); break; } default: return VA_STATUS_ERROR_OPERATION_FAILED; } return vdpau_get_VAStatus(vdp_status); } // vaGetImage VAStatus vdpau_GetImage( VADriverContextP ctx, VASurfaceID surface, int x, int y, unsigned int width, unsigned int height, VAImageID image ) { VDPAU_DRIVER_DATA_INIT; object_surface_p obj_surface = VDPAU_SURFACE(surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; object_image_p obj_image = VDPAU_IMAGE(image); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; VARectangle rect; rect.x = x; rect.y = y; rect.width = width; rect.height = height; return get_image(driver_data, obj_surface, obj_image, &rect); } // Put image to surface static VAStatus put_image( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_image_p obj_image, const VARectangle *src_rect, const VARectangle *dst_rect ) { VAImage * const image = &obj_image->image; VdpStatus vdp_status; uint8_t *src[3]; unsigned int src_stride[3]; int i; #if 0 /* Don't do anything if the surface is used for rendering for example */ /* XXX: VDPAU has no API to inform when decoding is completed... */ if (obj_surface->va_surface_status != VASurfaceReady) return VA_STATUS_ERROR_SURFACE_BUSY; #endif /* RGBA to video surface requires color space conversion */ if (obj_image->vdp_rgba_output_surface != VDP_INVALID_HANDLE) return VA_STATUS_ERROR_OPERATION_FAILED; /* VDPAU does not support partial video surface updates */ if (src_rect->x != 0 || src_rect->y != 0 || src_rect->width != image->width || src_rect->height != image->height) return VA_STATUS_ERROR_OPERATION_FAILED; if (dst_rect->x != 0 || dst_rect->y != 0 || dst_rect->width != obj_surface->width || dst_rect->height != obj_surface->height) return VA_STATUS_ERROR_OPERATION_FAILED; if (src_rect->width != dst_rect->width || src_rect->height != dst_rect->height) return VA_STATUS_ERROR_OPERATION_FAILED; object_buffer_p obj_buffer = VDPAU_BUFFER(image->buf); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; switch (image->format.fourcc) { case VA_FOURCC('I','4','2','0'): src[0] = (uint8_t *)obj_buffer->buffer_data + image->offsets[0]; src_stride[0] = image->pitches[0]; src[1] = (uint8_t *)obj_buffer->buffer_data + image->offsets[2]; src_stride[1] = image->pitches[2]; src[2] = (uint8_t *)obj_buffer->buffer_data + image->offsets[1]; src_stride[2] = image->pitches[1]; break; default: for (i = 0; i < image->num_planes; i++) { src[i] = (uint8_t *)obj_buffer->buffer_data + image->offsets[i]; src_stride[i] = image->pitches[i]; } break; } /* XXX: only support YCbCr surfaces for now */ if (obj_image->vdp_format_type != VDP_IMAGE_FORMAT_TYPE_YCBCR) return VA_STATUS_ERROR_OPERATION_FAILED; vdp_status = vdpau_video_surface_put_bits_ycbcr( driver_data, obj_surface->vdp_surface, obj_image->vdp_format, src, src_stride ); return vdpau_get_VAStatus(vdp_status); } // vaPutImage VAStatus vdpau_PutImage( VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, unsigned int width, unsigned int height, int dest_x, int dest_y ) { VDPAU_DRIVER_DATA_INIT; object_surface_p obj_surface = VDPAU_SURFACE(surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; object_image_p obj_image = VDPAU_IMAGE(image); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; VARectangle src_rect, dst_rect; src_rect.x = src_x; src_rect.y = src_y; src_rect.width = width; src_rect.height = height; dst_rect.x = dest_x; dst_rect.y = dest_y; dst_rect.width = width; dst_rect.height = height; return put_image(driver_data, obj_surface, obj_image, &src_rect, &dst_rect); } // vaPutImage2 VAStatus vdpau_PutImage_full( VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height ) { VDPAU_DRIVER_DATA_INIT; object_surface_p obj_surface = VDPAU_SURFACE(surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; object_image_p obj_image = VDPAU_IMAGE(image); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; VARectangle src_rect, dst_rect; src_rect.x = src_x; src_rect.y = src_y; src_rect.width = src_width; src_rect.height = src_height; dst_rect.x = dest_x; dst_rect.y = dest_y; dst_rect.width = dest_width; dst_rect.height = dest_height; return put_image(driver_data, obj_surface, obj_image, &src_rect, &dst_rect); } vdpau-driver-0.7.4/src/vdpau_image.h000066400000000000000000000063331203356434100173610ustar00rootroot00000000000000/* * vdpau_image.h - VDPAU backend for VA-API (VA images) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_IMAGE_H #define VDPAU_IMAGE_H #include "vdpau_driver.h" typedef enum { VDP_IMAGE_FORMAT_TYPE_YCBCR = 1, VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_IMAGE_FORMAT_TYPE_INDEXED } VdpImageFormatType; typedef struct object_image object_image_t; struct object_image { struct object_base base; VAImage image; VdpImageFormatType vdp_format_type; uint32_t vdp_format; VdpOutputSurface vdp_rgba_output_surface; uint32_t *vdp_palette; }; // vaQueryImageFormats VAStatus vdpau_QueryImageFormats( VADriverContextP ctx, VAImageFormat *format_list, int *num_formats ) attribute_hidden; // vaCreateImage VAStatus vdpau_CreateImage( VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image ) attribute_hidden; // vaDestroyImage VAStatus vdpau_DestroyImage( VADriverContextP ctx, VAImageID image_id ) attribute_hidden; // vaDeriveImage VAStatus vdpau_DeriveImage( VADriverContextP ctx, VASurfaceID surface, VAImage *image ) attribute_hidden; // vaSetImagePalette VAStatus vdpau_SetImagePalette( VADriverContextP ctx, VAImageID image, unsigned char *palette ) attribute_hidden; // vaGetImage VAStatus vdpau_GetImage( VADriverContextP ctx, VASurfaceID surface, int x, int y, unsigned int width, unsigned int height, VAImageID image_id ) attribute_hidden; // vaPutImage VAStatus vdpau_PutImage( VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, unsigned int width, unsigned int height, int dest_x, int dest_y ) attribute_hidden; // vaPutImage2 VAStatus vdpau_PutImage_full( VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height ) attribute_hidden; #endif /* VDPAU_IMAGE_H */ vdpau-driver-0.7.4/src/vdpau_mixer.c000066400000000000000000000331241203356434100174140ustar00rootroot00000000000000/* * vdpau_mixer.c - VDPAU backend for VA-API (video mixer abstraction) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_mixer.h" #include "vdpau_video.h" #include #define VDPAU_MAX_VIDEO_MIXER_PARAMS 4 #define VDPAU_MAX_VIDEO_MIXER_FEATURES 20 static inline int video_mixer_check_params( object_mixer_p obj_mixer, object_surface_p obj_surface ) { return (obj_mixer->width == obj_surface->width && obj_mixer->height == obj_surface->height && obj_mixer->vdp_chroma_type == obj_surface->vdp_chroma_type); } static inline void video_mixer_init_deint_surfaces(object_mixer_p obj_mixer) { unsigned int i; for (i = 0; i < VDPAU_MAX_VIDEO_MIXER_DEINT_SURFACES; i++) obj_mixer->deint_surfaces[i] = VDP_INVALID_HANDLE; } /** Checks wether video mixer supports a specific feature */ static inline VdpBool video_mixer_has_feature( vdpau_driver_data_t *driver_data, VdpVideoMixerFeature feature ) { VdpBool is_supported = VDP_FALSE; VdpStatus status; status = vdpau_video_mixer_query_feature_support( driver_data, driver_data->vdp_device, feature, &is_supported ); return (VDPAU_CHECK_STATUS(status, "VdpVideoMixerQueryFeatureSupport()") && is_supported); } object_mixer_p video_mixer_create( vdpau_driver_data_t *driver_data, object_surface_p obj_surface ) { VAGenericID mixer_id = object_heap_allocate(&driver_data->mixer_heap); if (mixer_id == VA_INVALID_ID) return NULL; object_mixer_p obj_mixer = VDPAU_MIXER(mixer_id); if (!obj_mixer) return NULL; obj_mixer->refcount = 1; obj_mixer->vdp_video_mixer = VDP_INVALID_HANDLE; obj_mixer->width = obj_surface->width; obj_mixer->height = obj_surface->height; obj_mixer->vdp_chroma_type = obj_surface->vdp_chroma_type; obj_mixer->vdp_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601; obj_mixer->vdp_procamp_mtime = 0; obj_mixer->vdp_bgcolor_mtime = 0; obj_mixer->hqscaling_level = 0; obj_mixer->va_scale = 0; VdpProcamp * const procamp = &obj_mixer->vdp_procamp; procamp->struct_version = VDP_PROCAMP_VERSION; procamp->brightness = 0.0; procamp->contrast = 1.0; procamp->saturation = 1.0; procamp->hue = 0.0; VdpVideoMixerParameter params[VDPAU_MAX_VIDEO_MIXER_PARAMS]; void *param_values[VDPAU_MAX_VIDEO_MIXER_PARAMS]; unsigned int n_params = 0; params[n_params] = VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH; param_values[n_params++] = &obj_mixer->width; params[n_params] = VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT; param_values[n_params++] = &obj_mixer->height; params[n_params] = VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE; param_values[n_params++] = &obj_mixer->vdp_chroma_type; VdpVideoMixerFeature feature, features[VDPAU_MAX_VIDEO_MIXER_FEATURES]; unsigned int i, n_features = 0; for (i = 1; i <= 9; i++) { feature = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i - 1; if (video_mixer_has_feature(driver_data, feature)) { features[n_features++] = feature; obj_mixer->hqscaling_level = i; } } video_mixer_init_deint_surfaces(obj_mixer); VdpStatus vdp_status; vdp_status = vdpau_video_mixer_create( driver_data, driver_data->vdp_device, n_features, features, n_params, params, param_values, &obj_mixer->vdp_video_mixer ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpVideoMixerCreate()")) { video_mixer_destroy(driver_data, obj_mixer); return NULL; } return obj_mixer; } object_mixer_p video_mixer_create_cached( vdpau_driver_data_t *driver_data, object_surface_p obj_surface ) { object_mixer_p obj_mixer = obj_surface->video_mixer; if (obj_mixer) return video_mixer_ref(driver_data, obj_mixer); object_heap_iterator iter; object_base_p obj = object_heap_first(&driver_data->mixer_heap, &iter); while (obj) { obj_mixer = (object_mixer_p)obj; if (video_mixer_check_params(obj_mixer, obj_surface)) return video_mixer_ref(driver_data, obj_mixer); obj = object_heap_next(&driver_data->mixer_heap, &iter); } return video_mixer_create(driver_data, obj_surface); } void video_mixer_destroy( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) { if (!obj_mixer) return; if (obj_mixer->vdp_video_mixer != VDP_INVALID_HANDLE) { vdpau_video_mixer_destroy(driver_data, obj_mixer->vdp_video_mixer); obj_mixer->vdp_video_mixer = VDP_INVALID_HANDLE; } object_heap_free(&driver_data->mixer_heap, (object_base_p)obj_mixer); } object_mixer_p video_mixer_ref( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) { if (obj_mixer) ++obj_mixer->refcount; return obj_mixer; } void video_mixer_unref( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) { if (obj_mixer && --obj_mixer->refcount == 0) video_mixer_destroy(driver_data, obj_mixer); } static VdpStatus video_mixer_update_csc_matrix( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer, VdpColorStandard vdp_colorspace ) { uint64_t new_mtime = obj_mixer->vdp_procamp_mtime; unsigned int i; for (i = 0; i < driver_data->va_display_attrs_count; i++) { VADisplayAttribute * const attr = &driver_data->va_display_attrs[i]; if (obj_mixer->vdp_procamp_mtime >= driver_data->va_display_attrs_mtime[i]) continue; float *vp, v = attr->value / 100.0; switch (attr->type) { case VADisplayAttribBrightness: /* VDPAU range: -1.0 to 1.0 */ vp = &obj_mixer->vdp_procamp.brightness; break; case VADisplayAttribContrast: /* VDPAU range: 0.0 to 10.0 */ vp = &obj_mixer->vdp_procamp.contrast; goto do_range_0_10; case VADisplayAttribSaturation: /* VDPAU range: 0.0 to 10.0 */ vp = &obj_mixer->vdp_procamp.saturation; do_range_0_10: if (attr->value > 0) /* scale VA:0-100 to VDPAU:1.0-10.0 */ v *= 9.0; v += 1.0; break; case VADisplayAttribHue: /* VDPAU range: -PI to PI */ vp = &obj_mixer->vdp_procamp.hue; v *= M_PI; break; default: vp = NULL; break; } if (vp) { *vp = v; if (new_mtime < driver_data->va_display_attrs_mtime[i]) new_mtime = driver_data->va_display_attrs_mtime[i]; } } /* Commit changes, if any */ if (new_mtime > obj_mixer->vdp_procamp_mtime || vdp_colorspace != obj_mixer->vdp_colorspace) { VdpCSCMatrix vdp_matrix; VdpStatus vdp_status; static const VdpVideoMixerAttribute attrs[1] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; const void *attr_values[1] = { &vdp_matrix }; vdp_status = vdpau_generate_csc_matrix( driver_data, &obj_mixer->vdp_procamp, vdp_colorspace, &vdp_matrix ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpGenerateCSCMatrix()")) return vdp_status; vdp_status = vdpau_video_mixer_set_attribute_values( driver_data, obj_mixer->vdp_video_mixer, 1, attrs, attr_values ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpVideoMixerSetAttributeValues()")) return vdp_status; obj_mixer->vdp_colorspace = vdp_colorspace; obj_mixer->vdp_procamp_mtime = new_mtime; } return VDP_STATUS_OK; } VdpStatus video_mixer_set_background_color( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer, const VdpColor *vdp_color ) { VdpStatus vdp_status; VdpVideoMixerAttribute attrs[1]; const void *attr_values[1]; attrs[0] = VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR; attr_values[0] = vdp_color; vdp_status = vdpau_video_mixer_set_attribute_values( driver_data, obj_mixer->vdp_video_mixer, 1, attrs, attr_values ); return vdp_status; } static VdpStatus video_mixer_update_background_color( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) { unsigned int i; for (i = 0; i < driver_data->va_display_attrs_count; i++) { VADisplayAttribute * const attr = &driver_data->va_display_attrs[i]; if (attr->type != VADisplayAttribBackgroundColor) continue; if (obj_mixer->vdp_bgcolor_mtime < driver_data->va_display_attrs_mtime[i]) { VdpStatus vdp_status; VdpColor vdp_color; vdp_color.red = ((attr->value >> 16) & 0xff) / 255.0f; vdp_color.green = ((attr->value >> 8) & 0xff) / 255.0f; vdp_color.blue = (attr->value & 0xff)/ 255.0f; vdp_color.alpha = 1.0f; vdp_status = video_mixer_set_background_color( driver_data, obj_mixer, &vdp_color ); if (vdp_status != VDP_STATUS_OK) return vdp_status; obj_mixer->vdp_bgcolor_mtime = driver_data->va_display_attrs_mtime[i]; break; } } return VDP_STATUS_OK; } static VdpStatus video_mixer_update_scaling( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer, unsigned int va_scale ) { if (obj_mixer->va_scale == va_scale) return VDP_STATUS_OK; /* Only HQ scaling is supported, other flags disable HQ scaling */ if (obj_mixer->hqscaling_level >= 1) { VdpVideoMixerFeature features[1]; VdpBool feature_enables[1]; features[0] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1; feature_enables[0] = (va_scale == VA_FILTER_SCALING_HQ ? VDP_TRUE : VDP_FALSE); VdpStatus vdp_status; vdp_status = vdpau_video_mixer_set_feature_enables( driver_data, obj_mixer->vdp_video_mixer, 1, features, feature_enables ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpVideoMixerSetFeatureEnables()")) return vdp_status; } obj_mixer->va_scale = va_scale; return VDP_STATUS_OK; } static inline void video_mixer_push_deint_surface( object_mixer_p obj_mixer, object_surface_p obj_surface ) { unsigned int i; for (i = VDPAU_MAX_VIDEO_MIXER_DEINT_SURFACES - 1; i >= 1; i--) obj_mixer->deint_surfaces[i] = obj_mixer->deint_surfaces[i - 1]; obj_mixer->deint_surfaces[0] = obj_surface->vdp_surface; } VdpStatus video_mixer_render( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer, object_surface_p obj_surface, VdpOutputSurface vdp_background, VdpOutputSurface vdp_output_surface, const VdpRect *vdp_src_rect, const VdpRect *vdp_dst_rect, unsigned int flags ) { VdpColorStandard vdp_colorspace; if (flags & VA_SRC_SMPTE_240) vdp_colorspace = VDP_COLOR_STANDARD_SMPTE_240M; else if (flags & VA_SRC_BT709) vdp_colorspace = VDP_COLOR_STANDARD_ITUR_BT_709; else vdp_colorspace = VDP_COLOR_STANDARD_ITUR_BT_601; VdpStatus vdp_status; vdp_status = video_mixer_update_csc_matrix( driver_data, obj_mixer, vdp_colorspace ); if (vdp_status != VDP_STATUS_OK) return vdp_status; vdp_status = video_mixer_update_background_color(driver_data, obj_mixer); if (vdp_status != VDP_STATUS_OK) return vdp_status; const unsigned int va_scale = flags & VA_FILTER_SCALING_MASK; vdp_status = video_mixer_update_scaling(driver_data, obj_mixer, va_scale); if (vdp_status != VDP_STATUS_OK) return vdp_status; VdpVideoMixerPictureStructure field; switch (flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD)) { case VA_TOP_FIELD: field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; break; case VA_BOTTOM_FIELD: field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; break; default: field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; break; } video_mixer_push_deint_surface(obj_mixer, obj_surface); if (flags & VA_CLEAR_DRAWABLE) vdp_background = VDP_INVALID_HANDLE; vdp_status = vdpau_video_mixer_render( driver_data, obj_mixer->vdp_video_mixer, vdp_background, NULL, field, VDPAU_MAX_VIDEO_MIXER_DEINT_SURFACES - 1, &obj_mixer->deint_surfaces[1], obj_mixer->deint_surfaces[0], 0, NULL, vdp_src_rect, vdp_output_surface, NULL, vdp_dst_rect, 0, NULL ); video_mixer_push_deint_surface(obj_mixer, obj_surface); return vdp_status; } vdpau-driver-0.7.4/src/vdpau_mixer.h000066400000000000000000000055071203356434100174250ustar00rootroot00000000000000/* * vdpau_mixer.h - VDPAU backend for VA-API (video mixer abstraction) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_MIXER_H #define VDPAU_MIXER_H #include "vdpau_driver.h" #define VDPAU_MAX_VIDEO_MIXER_DEINT_SURFACES 3 typedef struct object_mixer object_mixer_t; struct object_mixer { struct object_base base; unsigned int refcount; VdpVideoMixer vdp_video_mixer; VdpChromaType vdp_chroma_type; unsigned int width; unsigned int height; unsigned int hqscaling_level; unsigned int va_scale; VdpColorStandard vdp_colorspace; VdpProcamp vdp_procamp; uint64_t vdp_procamp_mtime; uint64_t vdp_bgcolor_mtime; VdpVideoSurface deint_surfaces[VDPAU_MAX_VIDEO_MIXER_DEINT_SURFACES]; }; object_mixer_p video_mixer_create( vdpau_driver_data_t *driver_data, object_surface_p obj_surface ) attribute_hidden; object_mixer_p video_mixer_create_cached( vdpau_driver_data_t *driver_data, object_surface_p obj_surface ) attribute_hidden; void video_mixer_destroy( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) attribute_hidden; object_mixer_p video_mixer_ref( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) attribute_hidden; void video_mixer_unref( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer ) attribute_hidden; VdpStatus video_mixer_set_background_color( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer, const VdpColor *vdp_color ) attribute_hidden; VdpStatus video_mixer_render( vdpau_driver_data_t *driver_data, object_mixer_p obj_mixer, object_surface_p obj_surface, VdpOutputSurface vdp_background, VdpOutputSurface vdp_output_surface, const VdpRect *vdp_src_rect, const VdpRect *vdp_dst_rect, unsigned int flags ) attribute_hidden; #endif /* VDPAU_MIXER_H */ vdpau-driver-0.7.4/src/vdpau_subpic.c000066400000000000000000000554611203356434100175650ustar00rootroot00000000000000/* * vdpau_subpic.c - VDPAU backend for VA-API (VA subpictures) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_subpic.h" #include "vdpau_video.h" #include "vdpau_image.h" #include "vdpau_buffer.h" #include "utils.h" #define DEBUG 1 #include "debug.h" // List of supported subpicture formats typedef struct { VdpImageFormatType vdp_format_type; uint32_t vdp_format; VAImageFormat va_format; unsigned int va_flags; } vdpau_subpic_format_map_t; static const vdpau_subpic_format_map_t vdpau_subpic_formats_map[VDPAU_MAX_SUBPICTURE_FORMATS + 1] = { { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_A4I4, { VA_FOURCC('A','I','4','4'), VA_MSB_FIRST, 8, }, 0 }, { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_I4A4, { VA_FOURCC('I','A','4','4'), VA_MSB_FIRST, 8, }, 0 }, { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_A8I8, { VA_FOURCC('A','I','8','8'), VA_MSB_FIRST, 16, }, 0 }, { VDP_IMAGE_FORMAT_TYPE_INDEXED, VDP_INDEXED_FORMAT_I8A8, { VA_FOURCC('I','A','8','8'), VA_MSB_FIRST, 16, }, 0 }, #ifdef WORDS_BIGENDIAN { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_B8G8R8A8, { VA_FOURCC('A','R','G','B'), VA_MSB_FIRST, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, VA_SUBPICTURE_GLOBAL_ALPHA }, { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_R8G8B8A8, { VA_FOURCC('A','B','G','R'), VA_MSB_FIRST, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, VA_SUBPICTURE_GLOBAL_ALPHA }, #else { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_B8G8R8A8, { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, VA_SUBPICTURE_GLOBAL_ALPHA }, { VDP_IMAGE_FORMAT_TYPE_RGBA, VDP_RGBA_FORMAT_R8G8B8A8, { VA_FOURCC('R','G','B','A'), VA_LSB_FIRST, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, VA_SUBPICTURE_GLOBAL_ALPHA }, #endif { 0, VDP_INVALID_HANDLE, } }; // Returns a suitable VDPAU subpicture format for the specified VA image format static const vdpau_subpic_format_map_t *get_format(const VAImageFormat *format) { unsigned int i; for (i = 0; vdpau_subpic_formats_map[i].va_format.fourcc != 0; i++) { const vdpau_subpic_format_map_t * const m = &vdpau_subpic_formats_map[i]; if (m->va_format.fourcc == format->fourcc && (m->vdp_format_type == VDP_IMAGE_FORMAT_TYPE_RGBA ? (m->va_format.byte_order == format->byte_order && m->va_format.red_mask == format->red_mask && m->va_format.green_mask == format->green_mask && m->va_format.blue_mask == format->blue_mask && m->va_format.alpha_mask == format->alpha_mask) : 1)) return m; } return NULL; } // Checks whether the VDPAU implementation supports the specified image format static inline VdpBool is_supported_format( vdpau_driver_data_t *driver_data, const vdpau_subpic_format_map_t *format) { VdpBool is_supported = VDP_FALSE; VdpStatus vdp_status; uint32_t max_width, max_height; switch (format->vdp_format_type) { case VDP_IMAGE_FORMAT_TYPE_RGBA: vdp_status = vdpau_bitmap_surface_query_capabilities( driver_data, driver_data->vdp_device, format->vdp_format, &is_supported, &max_width, &max_height ); break; case VDP_IMAGE_FORMAT_TYPE_INDEXED: vdp_status = vdpau_output_surface_query_put_bits_indexed_capabilities( driver_data, driver_data->vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, format->vdp_format, VDP_COLOR_TABLE_FORMAT_B8G8R8X8, &is_supported ); break; default: vdp_status = VDP_STATUS_ERROR; break; } return vdp_status == VDP_STATUS_OK && is_supported; } // Append association to the subpicture static int subpicture_add_association( object_subpicture_p obj_subpicture, SubpictureAssociationP assoc ) { SubpictureAssociationP *assocs; assocs = realloc_buffer( (void **)&obj_subpicture->assocs, &obj_subpicture->assocs_count_max, 1 + obj_subpicture->assocs_count, sizeof(obj_subpicture->assocs[0]) ); if (!assocs) return -1; assocs[obj_subpicture->assocs_count++] = assoc; return 0; } // Remove association at the specified index from the subpicture static inline int subpicture_remove_association_at(object_subpicture_p obj_subpicture, int index) { ASSERT(obj_subpicture->assocs && obj_subpicture->assocs_count > 0); if (!obj_subpicture->assocs || obj_subpicture->assocs_count == 0) return -1; /* Replace with the last association */ const unsigned int last = obj_subpicture->assocs_count - 1; obj_subpicture->assocs[index] = obj_subpicture->assocs[last]; obj_subpicture->assocs[last] = NULL; obj_subpicture->assocs_count--; return 0; } #if 0 // Remove association from the subpicture static int subpicture_remove_association( object_subpicture_p obj_subpicture, SubpictureAssociationP assoc ) { ASSERT(obj_subpicture->assocs && obj_subpicture->assocs_count > 0); if (!obj_subpicture->assocs || obj_subpicture->assocs_count == 0) return -1; unsigned int i; for (i = 0; i < obj_subpicture->assocs_count; i++) { if (obj_subpicture->assocs[i] == assoc) return subpicture_remove_association_at(obj_subpicture, i); } return -1; } #endif // Associate one surface to the subpicture VAStatus subpicture_associate_1( object_subpicture_p obj_subpicture, object_surface_p obj_surface, const VARectangle *src_rect, const VARectangle *dst_rect, unsigned int flags ) { /* we only support the VA_SUBPICTURE_GLOBAL_ALPHA flag */ if (flags & ~VA_SUBPICTURE_GLOBAL_ALPHA) return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED; SubpictureAssociationP assoc = malloc(sizeof(*assoc)); if (!assoc) return VA_STATUS_ERROR_ALLOCATION_FAILED; assoc->subpicture = obj_subpicture->base.id; assoc->surface = obj_surface->base.id; assoc->src_rect = *src_rect; assoc->dst_rect = *dst_rect; assoc->flags = flags; VAStatus status = surface_add_association(obj_surface, assoc); if (status != VA_STATUS_SUCCESS) { free(assoc); return status; } if (subpicture_add_association(obj_subpicture, assoc) < 0) { surface_remove_association(obj_surface, assoc); free(assoc); return VA_STATUS_ERROR_ALLOCATION_FAILED; } return VA_STATUS_SUCCESS; } // Associate surfaces to the subpicture static VAStatus associate_subpicture( vdpau_driver_data_t *driver_data, object_subpicture_p obj_subpicture, VASurfaceID *surfaces, unsigned int num_surfaces, const VARectangle *src_rect, const VARectangle *dst_rect, unsigned int flags ) { VAStatus status; unsigned int i; for (i = 0; i < num_surfaces; i++) { object_surface_p const obj_surface = VDPAU_SURFACE(surfaces[i]); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; status = subpicture_associate_1(obj_subpicture, obj_surface, src_rect, dst_rect, flags); if (status != VA_STATUS_SUCCESS) return status; } return VA_STATUS_SUCCESS; } // Deassociate one surface from the subpicture VAStatus subpicture_deassociate_1( object_subpicture_p obj_subpicture, object_surface_p obj_surface ) { ASSERT(obj_subpicture->assocs && obj_subpicture->assocs_count > 0); if (!obj_subpicture->assocs || obj_subpicture->assocs_count == 0) return VA_STATUS_ERROR_OPERATION_FAILED; unsigned int i; for (i = 0; i < obj_subpicture->assocs_count; i++) { SubpictureAssociationP const assoc = obj_subpicture->assocs[i]; ASSERT(assoc); if (assoc && assoc->surface == obj_surface->base.id) { surface_remove_association(obj_surface, assoc); subpicture_remove_association_at(obj_subpicture, i); free(assoc); return VA_STATUS_SUCCESS; } } return VA_STATUS_ERROR_OPERATION_FAILED; } // Deassociate surfaces from the subpicture static VAStatus deassociate_subpicture( vdpau_driver_data_t *driver_data, object_subpicture_p obj_subpicture, VASurfaceID *surfaces, unsigned int num_surfaces ) { VAStatus status, error = VA_STATUS_SUCCESS; unsigned int i; for (i = 0; i < num_surfaces; i++) { object_surface_p const obj_surface = VDPAU_SURFACE(surfaces[i]); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; status = subpicture_deassociate_1(obj_subpicture, obj_surface); if (status != VA_STATUS_SUCCESS) { /* Simply report the first error to the user */ if (error == VA_STATUS_SUCCESS) error = status; } } return error; } // Commit subpicture to VDPAU surface VAStatus commit_subpicture( vdpau_driver_data_p driver_data, object_subpicture_p obj_subpicture ) { object_image_p obj_image = VDPAU_IMAGE(obj_subpicture->image_id); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; ASSERT(obj_subpicture->width == obj_image->image.width); if (obj_subpicture->width != obj_image->image.width) return VA_STATUS_ERROR_OPERATION_FAILED; ASSERT(obj_subpicture->height == obj_image->image.height); if (obj_subpicture->height != obj_image->image.height) return VA_STATUS_ERROR_OPERATION_FAILED; object_buffer_p obj_buffer = VDPAU_BUFFER(obj_image->image.buf); if (!obj_buffer) return VA_STATUS_ERROR_INVALID_BUFFER; /* Update video surface only if the image (hence its buffer) was updated since our last synchronisation. NOTE: this assumes the user really unmaps the buffer when he is done with it, as it is actually required */ if (obj_subpicture->last_commit >= obj_buffer->mtime) return VA_STATUS_SUCCESS; VdpRect dirty_rect; dirty_rect.x0 = obj_subpicture->width; dirty_rect.y0 = obj_subpicture->height; dirty_rect.x1 = 0; dirty_rect.y1 = 0; unsigned int i; for (i = 0; i < obj_subpicture->assocs_count; i++) { const VARectangle * const rect = &obj_subpicture->assocs[i]->src_rect; dirty_rect.x0 = MIN(dirty_rect.x0, rect->x); dirty_rect.y0 = MIN(dirty_rect.y0, rect->y); dirty_rect.x1 = MAX(dirty_rect.x1, rect->x + rect->width); dirty_rect.y1 = MAX(dirty_rect.y1, rect->y + rect->height); } const uint8_t *src; uint32_t src_stride; src_stride = obj_image->image.pitches[0]; src = ((uint8_t *)obj_buffer->buffer_data + obj_image->image.offsets[0] + dirty_rect.y0 * obj_image->image.pitches[0] + dirty_rect.x0 * ((obj_image->image.format.bits_per_pixel + 7) / 8)); VdpStatus vdp_status; switch (obj_subpicture->vdp_format_type) { case VDP_IMAGE_FORMAT_TYPE_RGBA: vdp_status = vdpau_bitmap_surface_put_bits_native( driver_data, obj_subpicture->vdp_bitmap_surface, &src, &src_stride, &dirty_rect ); break; case VDP_IMAGE_FORMAT_TYPE_INDEXED: vdp_status = vdpau_output_surface_put_bits_indexed( driver_data, obj_subpicture->vdp_output_surface, obj_subpicture->vdp_format, &src, &src_stride, &dirty_rect, VDP_COLOR_TABLE_FORMAT_B8G8R8X8, obj_image->vdp_palette ); break; default: vdp_status = VDP_STATUS_ERROR; break; } if (vdp_status != VDP_STATUS_OK) return vdpau_get_VAStatus(vdp_status); obj_subpicture->last_commit = obj_buffer->mtime; return VA_STATUS_SUCCESS; } // Create subpicture with image static VAStatus create_subpicture( vdpau_driver_data_t *driver_data, object_image_p obj_image, VASubpictureID *subpicture ) { *subpicture = object_heap_allocate(&driver_data->subpicture_heap); if (*subpicture == VA_INVALID_ID) return VA_STATUS_ERROR_ALLOCATION_FAILED; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(*subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_ALLOCATION_FAILED; const vdpau_subpic_format_map_t *m = get_format(&obj_image->image.format); if (!is_supported_format(driver_data, m)) return VA_STATUS_ERROR_UNKNOWN; /* VA_STATUS_ERROR_UNSUPPORTED_FORMAT */ obj_subpicture->image_id = obj_image->base.id; obj_subpicture->assocs = NULL; obj_subpicture->assocs_count = 0; obj_subpicture->assocs_count_max = 0; obj_subpicture->width = obj_image->image.width; obj_subpicture->height = obj_image->image.height; obj_subpicture->vdp_bitmap_surface = VDP_INVALID_HANDLE; obj_subpicture->vdp_output_surface = VDP_INVALID_HANDLE; obj_subpicture->last_commit = 0; obj_subpicture->vdp_format_type = m->vdp_format_type; obj_subpicture->vdp_format = m->vdp_format; obj_subpicture->alpha = 1.0; VdpStatus vdp_status; switch (obj_subpicture->vdp_format_type) { case VDP_IMAGE_FORMAT_TYPE_RGBA: vdp_status = vdpau_bitmap_surface_create( driver_data, driver_data->vdp_device, obj_subpicture->vdp_format, obj_subpicture->width, obj_subpicture->height, VDP_FALSE, &obj_subpicture->vdp_bitmap_surface ); break; case VDP_IMAGE_FORMAT_TYPE_INDEXED: vdp_status = vdpau_output_surface_create( driver_data, driver_data->vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, obj_subpicture->width, obj_subpicture->height, &obj_subpicture->vdp_output_surface ); break; default: vdp_status = VDP_STATUS_ERROR; break; } return vdpau_get_VAStatus(vdp_status); } // Destroy subpicture static void destroy_subpicture( vdpau_driver_data_t *driver_data, object_subpicture_p obj_subpicture ) { object_surface_p obj_surface; VAStatus status; unsigned int i, n; if (obj_subpicture->assocs) { const unsigned int n_assocs = obj_subpicture->assocs_count; for (i = 0, n = 0; i < n_assocs; i++) { SubpictureAssociationP const assoc = obj_subpicture->assocs[0]; if (!assoc) continue; obj_surface = VDPAU_SURFACE(assoc->surface); if (!obj_surface) continue; status = subpicture_deassociate_1(obj_subpicture, obj_surface); if (status == VA_STATUS_SUCCESS) ++n; } if (n != n_assocs) vdpau_error_message("vaDestroySubpicture(): subpicture 0x%08x still " "has %d surfaces associated to it\n", obj_subpicture->base.id, n_assocs - n); free(obj_subpicture->assocs); obj_subpicture->assocs = NULL; } obj_subpicture->assocs_count = 0; obj_subpicture->assocs_count_max = 0; if (obj_subpicture->vdp_bitmap_surface != VDP_INVALID_HANDLE) { vdpau_bitmap_surface_destroy( driver_data, obj_subpicture->vdp_bitmap_surface ); obj_subpicture->vdp_bitmap_surface = VDP_INVALID_HANDLE; } if (obj_subpicture->vdp_output_surface != VDP_INVALID_HANDLE) { vdpau_output_surface_destroy( driver_data, obj_subpicture->vdp_output_surface ); obj_subpicture->vdp_output_surface = VDP_INVALID_HANDLE; } obj_subpicture->image_id = VA_INVALID_ID; object_heap_free(&driver_data->subpicture_heap, (object_base_p)obj_subpicture); } // vaQuerySubpictureFormats VAStatus vdpau_QuerySubpictureFormats( VADriverContextP ctx, VAImageFormat *format_list, unsigned int *flags, unsigned int *num_formats ) { VDPAU_DRIVER_DATA_INIT; int n; for (n = 0; vdpau_subpic_formats_map[n].va_format.fourcc != 0; n++) { const vdpau_subpic_format_map_t * const m = &vdpau_subpic_formats_map[n]; if (is_supported_format(driver_data, m)) { if (format_list) format_list[n] = m->va_format; if (flags) flags[n] = m->va_flags; } } if (num_formats) *num_formats = n; return VA_STATUS_SUCCESS; } // vaCreateSubpicture VAStatus vdpau_CreateSubpicture( VADriverContextP ctx, VAImageID image, VASubpictureID *subpicture ) { VDPAU_DRIVER_DATA_INIT; if (!subpicture) return VA_STATUS_ERROR_INVALID_PARAMETER; object_image_p obj_image = VDPAU_IMAGE(image); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; return create_subpicture(driver_data, obj_image, subpicture); } // vaDestroySubpicture VAStatus vdpau_DestroySubpicture( VADriverContextP ctx, VASubpictureID subpicture ) { VDPAU_DRIVER_DATA_INIT; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; destroy_subpicture(driver_data, obj_subpicture); return VA_STATUS_SUCCESS; } // vaSetSubpictureImage VAStatus vdpau_SetSubpictureImage( VADriverContextP ctx, VASubpictureID subpicture, VAImageID image ) { VDPAU_DRIVER_DATA_INIT; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; object_image_p obj_image = VDPAU_IMAGE(image); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; obj_subpicture->image_id = obj_image->base.id; return VA_STATUS_SUCCESS; } // vaSetSubpicturePalette (not a PUBLIC interface) VAStatus vdpau_SetSubpicturePalette( VADriverContextP ctx, VASubpictureID subpicture, unsigned char *palette ) { /* TODO */ return VA_STATUS_ERROR_OPERATION_FAILED; } // vaSetSubpictureChromaKey VAStatus vdpau_SetSubpictureChromakey( VADriverContextP ctx, VASubpictureID subpicture, unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask ) { VDPAU_DRIVER_DATA_INIT; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; obj_subpicture->chromakey_min = chromakey_min; obj_subpicture->chromakey_max = chromakey_max; obj_subpicture->chromakey_mask = chromakey_mask; return VA_STATUS_SUCCESS; } // vaSetSubpictureGlobalAlpha VAStatus vdpau_SetSubpictureGlobalAlpha( VADriverContextP ctx, VASubpictureID subpicture, float global_alpha ) { VDPAU_DRIVER_DATA_INIT; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; obj_subpicture->alpha = global_alpha; return VA_STATUS_SUCCESS; } // vaAssociateSubpicture VAStatus vdpau_AssociateSubpicture( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces, short src_x, short src_y, short dest_x, short dest_y, unsigned short width, unsigned short height, unsigned int flags ) { VDPAU_DRIVER_DATA_INIT; if (!target_surfaces || num_surfaces == 0) return VA_STATUS_SUCCESS; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; VARectangle src_rect, dst_rect; src_rect.x = src_x; src_rect.y = src_y; src_rect.width = width; src_rect.height = height; dst_rect.x = dest_x; dst_rect.y = dest_y; dst_rect.width = width; dst_rect.height = height; return associate_subpicture(driver_data, obj_subpicture, target_surfaces, num_surfaces, &src_rect, &dst_rect, flags); } // vaAssociateSubpicture2 VAStatus vdpau_AssociateSubpicture_full( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces, short src_x, short src_y, unsigned short src_width, unsigned short src_height, short dest_x, short dest_y, unsigned short dest_width, unsigned short dest_height, unsigned int flags ) { VDPAU_DRIVER_DATA_INIT; if (!target_surfaces || num_surfaces == 0) return VA_STATUS_SUCCESS; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; VARectangle src_rect, dst_rect; src_rect.x = src_x; src_rect.y = src_y; src_rect.width = src_width; src_rect.height = src_height; dst_rect.x = dest_x; dst_rect.y = dest_y; dst_rect.width = dest_width; dst_rect.height = dest_height; return associate_subpicture(driver_data, obj_subpicture, target_surfaces, num_surfaces, &src_rect, &dst_rect, flags); } // vaDeassociateSubpicture VAStatus vdpau_DeassociateSubpicture( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces ) { VDPAU_DRIVER_DATA_INIT; if (!target_surfaces || num_surfaces == 0) return VA_STATUS_SUCCESS; object_subpicture_p obj_subpicture = VDPAU_SUBPICTURE(subpicture); if (!obj_subpicture) return VA_STATUS_ERROR_INVALID_SUBPICTURE; return deassociate_subpicture(driver_data, obj_subpicture, target_surfaces, num_surfaces); } vdpau-driver-0.7.4/src/vdpau_subpic.h000066400000000000000000000115011203356434100175550ustar00rootroot00000000000000/* * vdpau_subpic.h - VDPAU backend for VA-API (VA subpictures) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_SUBPIC_H #define VDPAU_SUBPIC_H #include "vdpau_video.h" #include "vdpau_image.h" typedef struct object_subpicture object_subpicture_t; typedef struct object_subpicture *object_subpicture_p; struct object_subpicture { struct object_base base; VAImageID image_id; SubpictureAssociationP *assocs; unsigned int assocs_count; unsigned int assocs_count_max; unsigned int chromakey_min; unsigned int chromakey_max; unsigned int chromakey_mask; float alpha; unsigned int width; unsigned int height; VdpImageFormatType vdp_format_type; uint32_t vdp_format; VdpBitmapSurface vdp_bitmap_surface; VdpOutputSurface vdp_output_surface; uint64_t last_commit; }; // Associate one surface to the subpicture VAStatus subpicture_associate_1( object_subpicture_p obj_subpicture, object_surface_p obj_surface, const VARectangle *src_rect, const VARectangle *dst_rect, unsigned int flags ) attribute_hidden; // Deassociate one surface from the subpicture VAStatus subpicture_deassociate_1( object_subpicture_p obj_subpicture, object_surface_p obj_surface ) attribute_hidden; // Commit subpicture to VDPAU surface VAStatus commit_subpicture( vdpau_driver_data_p driver_data, object_subpicture_p obj_subpicture ) attribute_hidden; // vaQuerySubpictureFormats VAStatus vdpau_QuerySubpictureFormats( VADriverContextP ctx, VAImageFormat *format_list, unsigned int *flags, unsigned int *num_formats ) attribute_hidden; // vaCreateSubpicture VAStatus vdpau_CreateSubpicture( VADriverContextP ctx, VAImageID image, VASubpictureID *subpicture ) attribute_hidden; // vaDestroySubpicture VAStatus vdpau_DestroySubpicture( VADriverContextP ctx, VASubpictureID subpicture ) attribute_hidden; // vaSetSubpictureImage VAStatus vdpau_SetSubpictureImage( VADriverContextP ctx, VASubpictureID subpicture, VAImageID image ) attribute_hidden; // vaSetSubpicturePalette (not a PUBLIC interface) VAStatus vdpau_SetSubpicturePalette( VADriverContextP ctx, VASubpictureID subpicture, unsigned char *palette ) attribute_hidden; // vaSetSubpictureChromaKey VAStatus vdpau_SetSubpictureChromakey( VADriverContextP ctx, VASubpictureID subpicture, unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask ) attribute_hidden; // vaSetSubpictureGlobalAlpha VAStatus vdpau_SetSubpictureGlobalAlpha( VADriverContextP ctx, VASubpictureID subpicture, float global_alpha ) attribute_hidden; // vaAssociateSubpicture VAStatus vdpau_AssociateSubpicture( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces, short src_x, short src_y, short dest_x, short dest_y, unsigned short width, unsigned short height, unsigned int flags ) attribute_hidden; // vaAssociateSubpicture2 VAStatus vdpau_AssociateSubpicture_full( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces, short src_x, short src_y, unsigned short src_width, unsigned short src_height, short dest_x, short dest_y, unsigned short dest_width, unsigned short dest_height, unsigned int flags ) attribute_hidden; // vaDeassociateSubpicture VAStatus vdpau_DeassociateSubpicture( VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, int num_surfaces ) attribute_hidden; #endif /* VDPAU_SUBPIC_H */ vdpau-driver-0.7.4/src/vdpau_video.c000066400000000000000000000735701203356434100174070ustar00rootroot00000000000000/* * vdpau_video.c - VDPAU backend for VA-API * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_video.h" #include "vdpau_video_x11.h" #include "vdpau_decode.h" #include "vdpau_subpic.h" #include "vdpau_mixer.h" #include "vdpau_buffer.h" #include "utils.h" #define DEBUG 1 #include "debug.h" /* Define wait delay (in microseconds) for vaSyncSurface() implementation with polling. */ #define VDPAU_SYNC_DELAY 5000 // Translates VA-API chroma format to VdpChromaType static VdpChromaType get_VdpChromaType(int format) { switch (format) { case VA_RT_FORMAT_YUV420: return VDP_CHROMA_TYPE_420; case VA_RT_FORMAT_YUV422: return VDP_CHROMA_TYPE_422; case VA_RT_FORMAT_YUV444: return VDP_CHROMA_TYPE_444; } return (VdpChromaType)-1; } /* ====================================================================== */ /* === VA-API Implementation with VDPAU === */ /* ====================================================================== */ // Returns the maximum dimensions supported by the VDPAU implementation for that profile static inline VdpBool get_max_surface_size( vdpau_driver_data_t *driver_data, VdpDecoderProfile profile, uint32_t *pmax_width, uint32_t *pmax_height ) { VdpBool is_supported = VDP_FALSE; VdpStatus vdp_status; uint32_t max_level, max_references, max_width, max_height; if (pmax_width) *pmax_width = 0; if (pmax_height) *pmax_height = 0; vdp_status = vdpau_decoder_query_capabilities( driver_data, driver_data->vdp_device, profile, &is_supported, &max_level, &max_references, &max_width, &max_height ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpDecoderQueryCapabilities()")) return VDP_FALSE; if (!is_supported) return VDP_FALSE; if (pmax_width) *pmax_width = max_width; if (max_height) *pmax_height = max_height; return VDP_TRUE; } // vaGetConfigAttributes VAStatus vdpau_GetConfigAttributes( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs ) { VDPAU_DRIVER_DATA_INIT; VAStatus va_status = check_decoder(driver_data, profile, entrypoint); if (va_status != VA_STATUS_SUCCESS) return va_status; int i; for (i = 0; i < num_attribs; i++) { switch (attrib_list[i].type) { case VAConfigAttribRTFormat: attrib_list[i].value = VA_RT_FORMAT_YUV420; break; default: attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED; break; } } return VA_STATUS_SUCCESS; } static VAStatus vdpau_update_attribute(object_config_p obj_config, VAConfigAttrib *attrib) { int i; /* Check existing attrbiutes */ for (i = 0; obj_config->attrib_count < i; i++) { if (obj_config->attrib_list[i].type == attrib->type) { /* Update existing attribute */ obj_config->attrib_list[i].value = attrib->value; return VA_STATUS_SUCCESS; } } if (obj_config->attrib_count < VDPAU_MAX_CONFIG_ATTRIBUTES) { i = obj_config->attrib_count; obj_config->attrib_list[i].type = attrib->type; obj_config->attrib_list[i].value = attrib->value; obj_config->attrib_count++; return VA_STATUS_SUCCESS; } return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; } // vaDestroyConfig VAStatus vdpau_DestroyConfig(VADriverContextP ctx, VAConfigID config_id) { VDPAU_DRIVER_DATA_INIT; object_config_p obj_config = VDPAU_CONFIG(config_id); if (!obj_config) return VA_STATUS_ERROR_INVALID_CONFIG; object_heap_free(&driver_data->config_heap, (object_base_p)obj_config); return VA_STATUS_SUCCESS; } // vaCreateConfig VAStatus vdpau_CreateConfig( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id ) { VDPAU_DRIVER_DATA_INIT; VAStatus va_status; int configID; object_config_p obj_config; int i; /* Validate profile and entrypoint */ va_status = check_decoder(driver_data, profile, entrypoint); if (va_status != VA_STATUS_SUCCESS) return va_status; configID = object_heap_allocate(&driver_data->config_heap); if ((obj_config = VDPAU_CONFIG(configID)) == NULL) return VA_STATUS_ERROR_ALLOCATION_FAILED; obj_config->profile = profile; obj_config->entrypoint = entrypoint; obj_config->attrib_list[0].type = VAConfigAttribRTFormat; obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420; obj_config->attrib_count = 1; for(i = 0; i < num_attribs; i++) { va_status = vdpau_update_attribute(obj_config, &attrib_list[i]); if (va_status != VA_STATUS_SUCCESS) { vdpau_DestroyConfig(ctx, configID); return va_status; } } if (config_id) *config_id = configID; return va_status; } // vaQueryConfigAttributes VAStatus vdpau_QueryConfigAttributes( VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs ) { VDPAU_DRIVER_DATA_INIT; VAStatus va_status = VA_STATUS_SUCCESS; object_config_p obj_config; int i; obj_config = VDPAU_CONFIG(config_id); if (!obj_config) return VA_STATUS_ERROR_INVALID_CONFIG; if (profile) *profile = obj_config->profile; if (entrypoint) *entrypoint = obj_config->entrypoint; if (num_attribs) *num_attribs = obj_config->attrib_count; if (attrib_list) { for (i = 0; i < obj_config->attrib_count; i++) attrib_list[i] = obj_config->attrib_list[i]; } return va_status; } // Add subpicture association to surface // NOTE: the subpicture owns the SubpictureAssociation object int surface_add_association( object_surface_p obj_surface, SubpictureAssociationP assoc ) { /* Check that we don't already have this association */ if (obj_surface->assocs) { unsigned int i; for (i = 0; i < obj_surface->assocs_count; i++) { if (obj_surface->assocs[i] == assoc) return 0; if (obj_surface->assocs[i]->subpicture == assoc->subpicture) { /* XXX: this should not happen, but replace it in the interim */ ASSERT(obj_surface->assocs[i]->surface == assoc->surface); obj_surface->assocs[i] = assoc; return 0; } } } /* Check that we have not reached the maximum subpictures capacity yet */ if (obj_surface->assocs_count >= VDPAU_MAX_SUBPICTURES) return -1; /* Append this subpicture association */ SubpictureAssociationP *assocs; assocs = realloc_buffer( (void **)&obj_surface->assocs, &obj_surface->assocs_count_max, 1 + obj_surface->assocs_count, sizeof(obj_surface->assocs[0]) ); if (!assocs) return -1; assocs[obj_surface->assocs_count++] = assoc; return 0; } // Remove subpicture association from surface // NOTE: the subpicture owns the SubpictureAssociation object int surface_remove_association( object_surface_p obj_surface, SubpictureAssociationP assoc ) { if (!obj_surface->assocs || obj_surface->assocs_count == 0) return -1; unsigned int i; const unsigned int last = obj_surface->assocs_count - 1; for (i = 0; i <= last; i++) { if (obj_surface->assocs[i] == assoc) { /* Swap with the last subpicture */ obj_surface->assocs[i] = obj_surface->assocs[last]; obj_surface->assocs[last] = NULL; obj_surface->assocs_count--; return 0; } } return -1; } // vaDestroySurfaces VAStatus vdpau_DestroySurfaces( VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces ) { VDPAU_DRIVER_DATA_INIT; int i, j, n; for (i = num_surfaces - 1; i >= 0; i--) { object_surface_p obj_surface = VDPAU_SURFACE(surface_list[i]); ASSERT(obj_surface); if (!obj_surface) continue; if (obj_surface->vdp_surface != VDP_INVALID_HANDLE) { vdpau_video_surface_destroy(driver_data, obj_surface->vdp_surface); obj_surface->vdp_surface = VDP_INVALID_HANDLE; } for (j = 0; j < obj_surface->output_surfaces_count; j++) { output_surface_unref(driver_data, obj_surface->output_surfaces[j]); obj_surface->output_surfaces[j] = NULL; } free(obj_surface->output_surfaces); obj_surface->output_surfaces_count = 0; obj_surface->output_surfaces_count_max = 0; if (obj_surface->video_mixer) { video_mixer_unref(driver_data, obj_surface->video_mixer); obj_surface->video_mixer = NULL; } if (obj_surface->assocs) { object_subpicture_p obj_subpicture; VAStatus status; const unsigned int n_assocs = obj_surface->assocs_count; for (j = 0, n = 0; j < n_assocs; j++) { SubpictureAssociationP const assoc = obj_surface->assocs[0]; ASSERT(assoc); if (!assoc) continue; obj_subpicture = VDPAU_SUBPICTURE(assoc->subpicture); ASSERT(obj_subpicture); if (!obj_subpicture) continue; status = subpicture_deassociate_1(obj_subpicture, obj_surface); if (status == VA_STATUS_SUCCESS) ++n; } if (n != n_assocs) vdpau_error_message("vaDestroySurfaces(): surface 0x%08x still " "has %d subpictures associated to it\n", obj_surface->base.id, n_assocs - n); free(obj_surface->assocs); obj_surface->assocs = NULL; } obj_surface->assocs_count = 0; obj_surface->assocs_count_max = 0; object_heap_free(&driver_data->surface_heap, (object_base_p)obj_surface); } return VA_STATUS_SUCCESS; } // vaCreateSurfaces VAStatus vdpau_CreateSurfaces( VADriverContextP ctx, int width, int height, int format, int num_surfaces, VASurfaceID *surfaces ) { VDPAU_DRIVER_DATA_INIT; VAStatus va_status = VA_STATUS_SUCCESS; VdpVideoSurface vdp_surface = VDP_INVALID_HANDLE; VdpChromaType vdp_chroma_type = get_VdpChromaType(format); VdpStatus vdp_status; int i; /* We only support one format */ if (format != VA_RT_FORMAT_YUV420) return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; for (i = 0; i < num_surfaces; i++) { vdp_status = vdpau_video_surface_create( driver_data, driver_data->vdp_device, vdp_chroma_type, width, height, &vdp_surface ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpVideoSurfaceCreate()")) { va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; break; } int va_surface = object_heap_allocate(&driver_data->surface_heap); object_surface_p obj_surface = VDPAU_SURFACE(va_surface); if (!obj_surface) { va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; break; } obj_surface->va_context = VA_INVALID_ID; obj_surface->va_surface_status = VASurfaceReady; obj_surface->vdp_surface = vdp_surface; obj_surface->width = width; obj_surface->height = height; obj_surface->assocs = NULL; obj_surface->assocs_count = 0; obj_surface->assocs_count_max = 0; obj_surface->vdp_chroma_type = vdp_chroma_type; obj_surface->output_surfaces = NULL; obj_surface->output_surfaces_count = 0; obj_surface->output_surfaces_count_max = 0; obj_surface->video_mixer = NULL; surfaces[i] = va_surface; vdp_surface = VDP_INVALID_HANDLE; object_mixer_p obj_mixer; obj_mixer = video_mixer_create_cached(driver_data, obj_surface); if (!obj_mixer) { va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; break; } obj_surface->video_mixer = obj_mixer; } /* Error recovery */ if (va_status != VA_STATUS_SUCCESS) { if (vdp_surface != VDP_INVALID_HANDLE) vdpau_video_surface_destroy(driver_data, vdp_surface); vdpau_DestroySurfaces(ctx, surfaces, i); } return va_status; } // vaDestroyContext VAStatus vdpau_DestroyContext(VADriverContextP ctx, VAContextID context) { VDPAU_DRIVER_DATA_INIT; int i; object_context_p obj_context = VDPAU_CONTEXT(context); if (!obj_context) return VA_STATUS_ERROR_INVALID_CONTEXT; if (obj_context->gen_slice_data) { free(obj_context->gen_slice_data); obj_context->gen_slice_data = NULL; obj_context->gen_slice_data_size = 0; obj_context->gen_slice_data_size_max = 0; } if (obj_context->vdp_bitstream_buffers) { free(obj_context->vdp_bitstream_buffers); obj_context->vdp_bitstream_buffers = NULL; obj_context->vdp_bitstream_buffers_count = 0; obj_context->vdp_bitstream_buffers_count_max = 0; } if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) { vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder); obj_context->vdp_decoder = VDP_INVALID_HANDLE; } destroy_dead_va_buffers(driver_data, obj_context); if (obj_context->dead_buffers) { free(obj_context->dead_buffers); obj_context->dead_buffers = NULL; } if (obj_context->render_targets) { for (i = 0; i < obj_context->num_render_targets; i++) { object_surface_p obj_surface; obj_surface = VDPAU_SURFACE(obj_context->render_targets[i]); if (obj_surface) obj_surface->va_context = VA_INVALID_ID; } free(obj_context->render_targets); obj_context->render_targets = NULL; } obj_context->context_id = VA_INVALID_ID; obj_context->config_id = VA_INVALID_ID; obj_context->current_render_target = VA_INVALID_SURFACE; obj_context->picture_width = 0; obj_context->picture_height = 0; obj_context->num_render_targets = 0; obj_context->flags = 0; obj_context->dead_buffers_count = 0; obj_context->dead_buffers_count_max = 0; object_heap_free(&driver_data->context_heap, (object_base_p)obj_context); return VA_STATUS_SUCCESS; } // vaCreateContext VAStatus vdpau_CreateContext( VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context ) { VDPAU_DRIVER_DATA_INIT; if (context) *context = VA_INVALID_ID; object_config_p obj_config; if ((obj_config = VDPAU_CONFIG(config_id)) == NULL) return VA_STATUS_ERROR_INVALID_CONFIG; /* XXX: validate flag */ VdpDecoderProfile vdp_profile; uint32_t max_width, max_height; int i; vdp_profile = get_VdpDecoderProfile(obj_config->profile); if (!get_max_surface_size(driver_data, vdp_profile, &max_width, &max_height)) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; if (picture_width > max_width || picture_height > max_height) return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; VAContextID context_id = object_heap_allocate(&driver_data->context_heap); if (context_id == VA_INVALID_ID) return VA_STATUS_ERROR_ALLOCATION_FAILED; object_context_p obj_context = VDPAU_CONTEXT(context_id); if (!obj_context) return VA_STATUS_ERROR_ALLOCATION_FAILED; if (context) *context = context_id; obj_context->context_id = context_id; obj_context->config_id = config_id; obj_context->current_render_target = VA_INVALID_SURFACE; obj_context->picture_width = picture_width; obj_context->picture_height = picture_height; obj_context->num_render_targets = num_render_targets; obj_context->flags = flag; obj_context->max_ref_frames = -1; obj_context->render_targets = (VASurfaceID *) calloc(num_render_targets, sizeof(VASurfaceID)); obj_context->dead_buffers = NULL; obj_context->dead_buffers_count = 0; obj_context->dead_buffers_count_max = 0; obj_context->vdp_codec = get_VdpCodec(vdp_profile); obj_context->vdp_profile = vdp_profile; obj_context->vdp_decoder = VDP_INVALID_HANDLE; obj_context->gen_slice_data = NULL; obj_context->gen_slice_data_size = 0; obj_context->gen_slice_data_size_max = 0; obj_context->vdp_bitstream_buffers = NULL; obj_context->vdp_bitstream_buffers_count = 0; obj_context->vdp_bitstream_buffers_count_max = 0; if (!obj_context->render_targets) { vdpau_DestroyContext(ctx, context_id); return VA_STATUS_ERROR_ALLOCATION_FAILED; } for (i = 0; i < num_render_targets; i++) { object_surface_t *obj_surface; if ((obj_surface = VDPAU_SURFACE(render_targets[i])) == NULL) { vdpau_DestroyContext(ctx, context_id); return VA_STATUS_ERROR_INVALID_SURFACE; } obj_context->render_targets[i] = render_targets[i]; /* XXX: assume we can only associate a surface to a single context */ ASSERT(obj_surface->va_context == VA_INVALID_ID); obj_surface->va_context = context_id; } return VA_STATUS_SUCCESS; } // Query surface status VAStatus query_surface_status( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, VASurfaceStatus *status ) { VAStatus va_status = VA_STATUS_SUCCESS; if (obj_surface->va_surface_status == VASurfaceDisplaying) { unsigned int i, num_output_surfaces_displaying = 0; for (i = 0; i < obj_surface->output_surfaces_count; i++) { object_output_p obj_output = obj_surface->output_surfaces[i]; if (!obj_output) return VA_STATUS_ERROR_INVALID_SURFACE; VdpOutputSurface vdp_output_surface; vdp_output_surface = obj_output->vdp_output_surfaces[obj_output->displayed_output_surface]; if (vdp_output_surface == VDP_INVALID_HANDLE) continue; VdpPresentationQueueStatus vdp_queue_status; VdpTime vdp_dummy_time; VdpStatus vdp_status; vdp_status = vdpau_presentation_queue_query_surface_status( driver_data, obj_output->vdp_flip_queue, vdp_output_surface, &vdp_queue_status, &vdp_dummy_time ); va_status = vdpau_get_VAStatus(vdp_status); if (vdp_queue_status != VDP_PRESENTATION_QUEUE_STATUS_VISIBLE) ++num_output_surfaces_displaying; } if (num_output_surfaces_displaying == 0) obj_surface->va_surface_status = VASurfaceReady; } if (status) *status = obj_surface->va_surface_status; return va_status; } // vaQuerySurfaceStatus VAStatus vdpau_QuerySurfaceStatus( VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status ) { VDPAU_DRIVER_DATA_INIT; object_surface_p obj_surface = VDPAU_SURFACE(render_target); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; return query_surface_status(driver_data, obj_surface, status); } // Wait for the surface to complete pending operations VAStatus sync_surface( vdpau_driver_data_t *driver_data, object_surface_p obj_surface ) { /* VDPAU only supports status interface for in-progress display */ /* XXX: polling is bad but there currently is no alternative */ for (;;) { VASurfaceStatus va_surface_status; VAStatus va_status; va_status = query_surface_status( driver_data, obj_surface, &va_surface_status ); if (va_status != VA_STATUS_SUCCESS) return va_status; if (va_surface_status != VASurfaceDisplaying) break; delay_usec(VDPAU_SYNC_DELAY); } return VA_STATUS_SUCCESS; } // vaSyncSurface VAStatus vdpau_SyncSurface2( VADriverContextP ctx, VASurfaceID render_target ) { VDPAU_DRIVER_DATA_INIT; object_surface_p obj_surface = VDPAU_SURFACE(render_target); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; /* Assume that this shouldn't be called before vaEndPicture() */ object_context_p obj_context = VDPAU_CONTEXT(obj_surface->va_context); if (obj_context) { ASSERT(obj_context->current_render_target != obj_surface->base.id); if (obj_context->current_render_target == obj_surface->base.id) return VA_STATUS_ERROR_INVALID_CONTEXT; } return sync_surface(driver_data, obj_surface); } VAStatus vdpau_SyncSurface3( VADriverContextP ctx, VAContextID context, VASurfaceID render_target ) { VDPAU_DRIVER_DATA_INIT; object_surface_p obj_surface = VDPAU_SURFACE(render_target); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; /* Assume that this shouldn't be called before vaEndPicture() */ object_context_p obj_context = VDPAU_CONTEXT(context); if (obj_context) { ASSERT(obj_context->current_render_target != obj_surface->base.id); if (obj_context->current_render_target == obj_surface->base.id) return VA_STATUS_ERROR_INVALID_CONTEXT; } return sync_surface(driver_data, obj_surface); } // Ensure VA Display Attributes are initialized static int ensure_display_attributes(vdpau_driver_data_t *driver_data) { VADisplayAttribute *attr; if (driver_data->va_display_attrs_count > 0) return 0; memset(driver_data->va_display_attrs_mtime, 0, sizeof(driver_data->va_display_attrs_mtime)); attr = &driver_data->va_display_attrs[0]; attr->type = VADisplayAttribDirectSurface; attr->value = 0; /* VdpVideoSurface is copied into VdpOutputSurface */ attr->min_value = attr->value; attr->max_value = attr->value; attr->flags = VA_DISPLAY_ATTRIB_GETTABLE; attr++; attr->type = VADisplayAttribBrightness; attr->value = 0; attr->min_value = -100; attr->max_value = 100; attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; attr++; attr->type = VADisplayAttribContrast; attr->value = 0; attr->min_value = -100; attr->max_value = 100; attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; attr++; attr->type = VADisplayAttribHue; attr->value = 0; attr->min_value = -100; attr->max_value = 100; attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; attr++; attr->type = VADisplayAttribSaturation; attr->value = 0; attr->min_value = -100; attr->max_value = 100; attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; attr++; attr->type = VADisplayAttribBackgroundColor; attr->value = 0; attr->min_value = 0; attr->max_value = 0xffffff; attr->flags = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE; attr++; driver_data->va_display_attrs_count = attr - driver_data->va_display_attrs; ASSERT(driver_data->va_display_attrs_count <= VDPAU_MAX_DISPLAY_ATTRIBUTES); return 0; } // Look up for the specified VA display attribute static VADisplayAttribute * get_display_attribute( vdpau_driver_data_t *driver_data, VADisplayAttribType type ) { if (ensure_display_attributes(driver_data) < 0) return NULL; unsigned int i; for (i = 0; i < driver_data->va_display_attrs_count; i++) { if (driver_data->va_display_attrs[i].type == type) return &driver_data->va_display_attrs[i]; } return NULL; } // vaQueryDisplayAttributes VAStatus vdpau_QueryDisplayAttributes( VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes ) { VDPAU_DRIVER_DATA_INIT; if (ensure_display_attributes(driver_data) < 0) return VA_STATUS_ERROR_OPERATION_FAILED; if (attr_list) memcpy(attr_list, driver_data->va_display_attrs, driver_data->va_display_attrs_count * sizeof(attr_list[0])); if (num_attributes) *num_attributes = driver_data->va_display_attrs_count; return VA_STATUS_SUCCESS; } // vaGetDisplayAttributes VAStatus vdpau_GetDisplayAttributes( VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes ) { VDPAU_DRIVER_DATA_INIT; unsigned int i; for (i = 0; i < num_attributes; i++) { VADisplayAttribute * const dst_attr = &attr_list[i]; VADisplayAttribute *src_attr; src_attr = get_display_attribute(driver_data, dst_attr->type); if (src_attr && (src_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) != 0) { dst_attr->min_value = src_attr->min_value; dst_attr->max_value = src_attr->max_value; dst_attr->value = src_attr->value; } else dst_attr->flags &= ~VA_DISPLAY_ATTRIB_GETTABLE; } return VA_STATUS_SUCCESS; } // vaSetDisplayAttributes VAStatus vdpau_SetDisplayAttributes( VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes ) { VDPAU_DRIVER_DATA_INIT; unsigned int i; for (i = 0; i < num_attributes; i++) { VADisplayAttribute * const src_attr = &attr_list[i]; VADisplayAttribute *dst_attr; dst_attr = get_display_attribute(driver_data, src_attr->type); if (!dst_attr) return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; if ((dst_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) != 0) { dst_attr->value = src_attr->value; static uint64_t mtime; const int display_attr_index = dst_attr - driver_data->va_display_attrs; ASSERT(display_attr_index < VDPAU_MAX_DISPLAY_ATTRIBUTES); driver_data->va_display_attrs_mtime[display_attr_index] = ++mtime; } } return VA_STATUS_SUCCESS; } // vaDbgCopySurfaceToBuffer (not a PUBLIC interface) VAStatus vdpau_DbgCopySurfaceToBuffer( VADriverContextP ctx, VASurfaceID surface, void **buffer, unsigned int *stride ) { /* TODO */ return VA_STATUS_ERROR_UNKNOWN; } #if VA_CHECK_VERSION(0,30,0) // vaCreateSurfaceFromCIFrame VAStatus vdpau_CreateSurfaceFromCIFrame( VADriverContextP ctx, unsigned long frame_id, VASurfaceID *surface ) { /* TODO */ return VA_STATUS_ERROR_UNKNOWN; } // vaCreateSurfaceFromV4L2Buf VAStatus vdpau_CreateSurfaceFromV4L2Buf( VADriverContextP ctx, int v4l2_fd, struct v4l2_format *v4l2_fmt, struct v4l2_buffer *v4l2_buf, VASurfaceID *surface ) { /* TODO */ return VA_STATUS_ERROR_UNKNOWN; } // vaCopySurfaceToBuffer VAStatus vdpau_CopySurfaceToBuffer( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, void **buffer ) { /* TODO */ return VA_STATUS_ERROR_UNKNOWN; } #endif #if VA_CHECK_VERSION(0,31,1) // vaLockSurface VAStatus vdpau_LockSurface( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, unsigned int *buffer_name, void **buffer ) { if (fourcc) *fourcc = VA_FOURCC('N','V','1','2'); if (luma_stride) *luma_stride = 0; if (chroma_u_stride) *chroma_u_stride = 0; if (chroma_v_stride) *chroma_v_stride = 0; if (luma_offset) *luma_offset = 0; if (chroma_u_offset) *chroma_u_offset = 0; if (chroma_v_offset) *chroma_v_offset = 0; if (buffer_name) *buffer_name = 0; if (buffer) *buffer = NULL; return VA_STATUS_SUCCESS; } // vaUnlockSurface VAStatus vdpau_UnlockSurface( VADriverContextP ctx, VASurfaceID surface ) { return VA_STATUS_SUCCESS; } #endif vdpau-driver-0.7.4/src/vdpau_video.h000066400000000000000000000225421203356434100174050ustar00rootroot00000000000000/* * vdpau_video.h - VDPAU backend for VA-API (shareed data) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_VIDEO_H #define VDPAU_VIDEO_H #include "vdpau_driver.h" #include "vdpau_decode.h" typedef struct SubpictureAssociation *SubpictureAssociationP; struct SubpictureAssociation { VASubpictureID subpicture; VASurfaceID surface; VARectangle src_rect; VARectangle dst_rect; unsigned int flags; }; typedef struct object_config object_config_t; struct object_config { struct object_base base; VAProfile profile; VAEntrypoint entrypoint; VAConfigAttrib attrib_list[VDPAU_MAX_CONFIG_ATTRIBUTES]; int attrib_count; }; typedef struct object_context object_context_t; struct object_context { struct object_base base; VAContextID context_id; VAConfigID config_id; VASurfaceID current_render_target; int picture_width; int picture_height; int num_render_targets; int flags; int max_ref_frames; VASurfaceID *render_targets; VABufferID *dead_buffers; uint32_t dead_buffers_count; uint32_t dead_buffers_count_max; void *last_pic_param; void *last_slice_params; unsigned int last_slice_params_count; VdpCodec vdp_codec; VdpDecoderProfile vdp_profile; VdpDecoder vdp_decoder; uint8_t *gen_slice_data; unsigned int gen_slice_data_size; unsigned int gen_slice_data_size_max; VdpBitstreamBuffer *vdp_bitstream_buffers; unsigned int vdp_bitstream_buffers_count; unsigned int vdp_bitstream_buffers_count_max; union { VdpPictureInfoMPEG1Or2 mpeg2; #if HAVE_VDPAU_MPEG4 VdpPictureInfoMPEG4Part2 mpeg4; #endif VdpPictureInfoH264 h264; VdpPictureInfoVC1 vc1; } vdp_picture_info; }; typedef struct object_surface object_surface_t; struct object_surface { struct object_base base; VAContextID va_context; VASurfaceStatus va_surface_status; VdpVideoSurface vdp_surface; object_output_p *output_surfaces; unsigned int output_surfaces_count; unsigned int output_surfaces_count_max; object_mixer_p video_mixer; unsigned int width; unsigned int height; VdpChromaType vdp_chroma_type; SubpictureAssociationP *assocs; unsigned int assocs_count; unsigned int assocs_count_max; }; // Query surface status VAStatus query_surface_status( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, VASurfaceStatus *status ) attribute_hidden; // Wait for the surface to complete pending operations VAStatus sync_surface( vdpau_driver_data_t *driver_data, object_surface_p obj_surface ) attribute_hidden; // Add subpicture association to surface // NOTE: the subpicture owns the SubpictureAssociation object int surface_add_association( object_surface_p obj_surface, SubpictureAssociationP assoc ) attribute_hidden; // Remove subpicture association from surface // NOTE: the subpicture owns the SubpictureAssociation object int surface_remove_association( object_surface_p obj_surface, SubpictureAssociationP assoc ) attribute_hidden; // vaGetConfigAttributes VAStatus vdpau_GetConfigAttributes( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs ) attribute_hidden; // vaCreateConfig VAStatus vdpau_CreateConfig( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id ) attribute_hidden; // vaDestroyConfig VAStatus vdpau_DestroyConfig( VADriverContextP ctx, VAConfigID config_id ) attribute_hidden; // vaQueryConfigAttributes VAStatus vdpau_QueryConfigAttributes( VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs ) attribute_hidden; // vaCreateSurfaces VAStatus vdpau_CreateSurfaces( VADriverContextP ctx, int width, int height, int format, int num_surfaces, VASurfaceID *surfaces ) attribute_hidden; // vaDestroySurfaces VAStatus vdpau_DestroySurfaces( VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces ) attribute_hidden; // vaCreateContext VAStatus vdpau_CreateContext( VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context ) attribute_hidden; // vaDestroyContext VAStatus vdpau_DestroyContext( VADriverContextP ctx, VAContextID context ) attribute_hidden; // vaQuerySurfaceStatus VAStatus vdpau_QuerySurfaceStatus( VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status ) attribute_hidden; // vaSyncSurface 2-args variant (>= 0.31) VAStatus vdpau_SyncSurface2( VADriverContextP ctx, VASurfaceID render_target ) attribute_hidden; // vaSyncSurface 3-args variant (<= 0.30) VAStatus vdpau_SyncSurface3( VADriverContextP ctx, VAContextID context, VASurfaceID render_target ) attribute_hidden; // vaQueryDisplayAttributes VAStatus vdpau_QueryDisplayAttributes( VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes ) attribute_hidden; // vaGetDisplayAttributes VAStatus vdpau_GetDisplayAttributes( VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes ) attribute_hidden; // vaSetDisplayAttributes VAStatus vdpau_SetDisplayAttributes( VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes ) attribute_hidden; // vaDbgCopySurfaceToBuffer (not a PUBLIC interface) VAStatus vdpau_DbgCopySurfaceToBuffer( VADriverContextP ctx, VASurfaceID surface, void **buffer, unsigned int *stride ) attribute_hidden; #if VA_CHECK_VERSION(0,30,0) // vaCreateSurfaceFromCIFrame VAStatus vdpau_CreateSurfaceFromCIFrame( VADriverContextP ctx, unsigned long frame_id, VASurfaceID *surface ) attribute_hidden; // vaCreateSurfaceFromV4L2Buf VAStatus vdpau_CreateSurfaceFromV4L2Buf( VADriverContextP ctx, int v4l2_fd, struct v4l2_format *v4l2_fmt, struct v4l2_buffer *v4l2_buf, VASurfaceID *surface ) attribute_hidden; // vaCopySurfaceToBuffer VAStatus vdpau_CopySurfaceToBuffer( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, void **buffer ) attribute_hidden; #endif #if VA_CHECK_VERSION(0,31,1) // vaLockSurface VAStatus vdpau_LockSurface( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, unsigned int *buffer_name, void **buffer ) attribute_hidden; // vaUnlockSurface VAStatus vdpau_UnlockSurface( VADriverContextP ctx, VASurfaceID surface ) attribute_hidden; #endif #endif /* VDPAU_VIDEO_H */ vdpau-driver-0.7.4/src/vdpau_video_glx.c000066400000000000000000000540311203356434100202500ustar00rootroot00000000000000/* * vdpau_video_glx.c - VDPAU backend for VA-API (GLX rendering) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #define _GNU_SOURCE 1 /* RTLD_NEXT */ #include "sysdeps.h" #include "vdpau_mixer.h" #include "vdpau_video.h" #include "vdpau_video_glx.h" #include "vdpau_video_x11.h" #include "utils.h" #include "utils_glx.h" #include #include #include #define DEBUG 1 #include "debug.h" /* Use VDPAU/GL interop: * 1: VdpVideoSurface (TODO) * 2: VdpOutputSurface */ #define VDPAU_GL_INTEROP 2 static int get_vdpau_gl_interop_env(void) { GLVTable * const gl_vtable = gl_get_vtable(); if (!gl_vtable || !gl_vtable->has_vdpau_interop) return 0; int vdpau_gl_interop; if (getenv_int("VDPAU_VIDEO_GL_INTEROP", &vdpau_gl_interop) < 0) vdpau_gl_interop = VDPAU_GL_INTEROP; if (vdpau_gl_interop < 0) vdpau_gl_interop = 0; else if (vdpau_gl_interop > 2) vdpau_gl_interop = 2; return vdpau_gl_interop; } static inline int vdpau_gl_interop(void) { static int g_vdpau_gl_interop = -1; if (g_vdpau_gl_interop < 0) g_vdpau_gl_interop = get_vdpau_gl_interop_env(); return g_vdpau_gl_interop; } // Ensure GLX TFP and FBO extensions are available static inline int ensure_extensions(void) { GLVTable * const gl_vtable = gl_get_vtable(); /* XXX: GLX_EXT_texture_from_pixmap is checked later */ return (gl_vtable && gl_vtable->has_framebuffer_object); } // Render GLX Pixmap to texture static void render_pixmap( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface ) { float tw, th; const GLenum target = obj_glx_surface->target; const unsigned int w = obj_glx_surface->width; const unsigned int h = obj_glx_surface->height; if (vdpau_gl_interop()) { GLVdpSurface * const gl_surface = obj_glx_surface->gl_surface; glBindTexture(gl_surface->target, gl_surface->textures[0]); object_output_p const obj_output = obj_glx_surface->gl_output; switch (target) { case GL_TEXTURE_2D: tw = (float)obj_output->width / obj_output->max_width; th = (float)obj_output->height / obj_output->max_height; break; case GL_TEXTURE_RECTANGLE_ARB: tw = (float)obj_output->width; th = (float)obj_output->height; break; default: tw = 0.0f; th = 0.0f; ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB); break; } } else { switch (target) { case GL_TEXTURE_2D: tw = 1.0f; th = 1.0f; break; case GL_TEXTURE_RECTANGLE_ARB: tw = (float)w; th = (float)h; break; default: tw = 0.0f; th = 0.0f; ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB); break; } } glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); { glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0); glTexCoord2f(0.0f, th ); glVertex2i(0, h); glTexCoord2f(tw , th ); glVertex2i(w, h); glTexCoord2f(tw , 0.0f); glVertex2i(w, 0); } glEnd(); } // Destroy VA/GLX surface static void destroy_surface(vdpau_driver_data_t *driver_data, VASurfaceID surface) { object_glx_surface_p obj_glx_surface = VDPAU_GLX_SURFACE(surface); if (obj_glx_surface->gl_surface) { gl_vdpau_destroy_surface(obj_glx_surface->gl_surface); obj_glx_surface->gl_surface = NULL; } if (obj_glx_surface->gl_output) { output_surface_destroy(driver_data, obj_glx_surface->gl_output); obj_glx_surface->gl_output = NULL; } if (vdpau_gl_interop()) gl_vdpau_exit(); if (obj_glx_surface->fbo) { gl_destroy_framebuffer_object(obj_glx_surface->fbo); obj_glx_surface->fbo = NULL; } if (obj_glx_surface->pixo) { gl_destroy_pixmap_object(obj_glx_surface->pixo); obj_glx_surface->pixo = NULL; } object_heap_free(&driver_data->glx_surface_heap, (object_base_p)obj_glx_surface); } // Check internal texture format is supported static int is_supported_internal_format(GLenum format) { /* XXX: we don't support other textures than RGBA */ switch (format) { case 4: case GL_RGBA: case GL_RGBA8: return 1; } return 0; } // Create VA/GLX surface static VASurfaceID create_surface(vdpau_driver_data_t *driver_data, GLenum target, GLuint texture) { VASurfaceID surface = VA_INVALID_SURFACE; object_glx_surface_p obj_glx_surface; unsigned int internal_format, border_width, width, height; int is_error = 1; glBindTexture(target, texture); surface = object_heap_allocate(&driver_data->glx_surface_heap); if (surface == VA_INVALID_SURFACE) goto end; obj_glx_surface = VDPAU_GLX_SURFACE(surface); if (!obj_glx_surface) goto end; obj_glx_surface->gl_context = NULL; obj_glx_surface->gl_surface = NULL; obj_glx_surface->gl_output = NULL; obj_glx_surface->target = target; obj_glx_surface->texture = texture; obj_glx_surface->va_surface = VA_INVALID_SURFACE; obj_glx_surface->pixo = NULL; obj_glx_surface->fbo = NULL; if (!gl_get_texture_param(target, GL_TEXTURE_INTERNAL_FORMAT, &internal_format)) goto end; if (!is_supported_internal_format(internal_format)) goto end; /* Check texture dimensions */ if (!gl_get_texture_param(target, GL_TEXTURE_BORDER, &border_width)) goto end; if (!gl_get_texture_param(target, GL_TEXTURE_WIDTH, &width)) goto end; if (!gl_get_texture_param(target, GL_TEXTURE_HEIGHT, &height)) goto end; width -= 2 * border_width; height -= 2 * border_width; if (width == 0 || height == 0) goto end; obj_glx_surface->width = width; obj_glx_surface->height = height; /* Initialize VDPAU/GL layer */ if (vdpau_gl_interop()) { if (!gl_vdpau_init(driver_data->vdp_device, driver_data->vdp_get_proc_address)) goto end; } /* Create Pixmaps for TFP */ else { obj_glx_surface->pixo = gl_create_pixmap_object( driver_data->x11_dpy, target, width, height ); if (!obj_glx_surface->pixo) goto end; } is_error = 0; end: glBindTexture(target, 0); if (is_error && surface != VA_INVALID_SURFACE) { destroy_surface(driver_data, surface); surface = VA_INVALID_SURFACE; } return surface; } // vaCreateSurfaceGLX VAStatus vdpau_CreateSurfaceGLX( VADriverContextP ctx, unsigned int target, unsigned int texture, void **gl_surface ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); if (!gl_surface) return VA_STATUS_ERROR_INVALID_PARAMETER; /* Make sure it is a valid GL texture object */ if (!glIsTexture(texture)) return VA_STATUS_ERROR_INVALID_PARAMETER; /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; GLContextState old_cs, *new_cs; gl_get_current_context(&old_cs); new_cs = gl_create_context(driver_data->x11_dpy, driver_data->x11_screen, &old_cs); if (!new_cs) return VA_STATUS_ERROR_ALLOCATION_FAILED; if (!gl_set_current_context(new_cs, NULL)) return VA_STATUS_ERROR_OPERATION_FAILED; gl_init_context(new_cs); VASurfaceID surface = create_surface(driver_data, target, texture); if (surface == VA_INVALID_SURFACE) return VA_STATUS_ERROR_ALLOCATION_FAILED; object_glx_surface_p obj_glx_surface = VDPAU_GLX_SURFACE(surface); *gl_surface = obj_glx_surface; obj_glx_surface->gl_context = new_cs; gl_set_current_context(&old_cs, NULL); return VA_STATUS_SUCCESS; } // vaDestroySurfaceGLX VAStatus vdpau_DestroySurfaceGLX( VADriverContextP ctx, void *gl_surface ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs, *new_cs = obj_glx_surface->gl_context; if (!gl_set_current_context(new_cs, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; destroy_surface(driver_data, obj_glx_surface->base.id); gl_destroy_context(new_cs); gl_set_current_context(&old_cs, NULL); return VA_STATUS_SUCCESS; } // Forward declarations static VAStatus deassociate_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface ); // vaAssociateSurfaceGLX static VAStatus associate_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface, object_surface_p obj_surface, unsigned int flags ) { /* XXX: optimise case where we are associating the same VA surface as before an no changed occurred to it */ VAStatus va_status; va_status = deassociate_glx_surface(driver_data, obj_glx_surface); if (va_status != VA_STATUS_SUCCESS) return va_status; VARectangle src_rect, dst_rect; src_rect.x = 0; src_rect.y = 0; src_rect.width = obj_surface->width; src_rect.height = obj_surface->height; /* Render to VDPAU output surface */ if (vdpau_gl_interop()) { if (!obj_glx_surface->gl_output) { obj_glx_surface->gl_output = output_surface_create( driver_data, None, obj_surface->width, obj_surface->height ); if (!obj_glx_surface->gl_output) return VA_STATUS_ERROR_ALLOCATION_FAILED; /* XXX: use multiple output surfaces? */ int status; status = output_surface_ensure_size( driver_data, obj_glx_surface->gl_output, obj_surface->width, obj_surface->height ); if (status < 0) return VA_STATUS_ERROR_ALLOCATION_FAILED; obj_glx_surface->gl_surface = gl_vdpau_create_output_surface( obj_glx_surface->target, obj_glx_surface->gl_output->vdp_output_surfaces[0] ); if (!obj_glx_surface->gl_surface) return VA_STATUS_ERROR_ALLOCATION_FAILED; /* Make sure background color is black with alpha set to 0xff */ VdpStatus vdp_status; static const VdpColor bgcolor = { 0.0f, 0.0f, 0.0f, 1.0f }; vdp_status = video_mixer_set_background_color( driver_data, obj_surface->video_mixer, &bgcolor ); if (vdp_status != VDP_STATUS_OK) return vdpau_get_VAStatus(vdp_status); } dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = obj_surface->width; dst_rect.height = obj_surface->height; /* Render the video surface to the output surface */ va_status = render_surface( driver_data, obj_surface, obj_glx_surface->gl_output, &src_rect, &dst_rect, flags | VA_CLEAR_DRAWABLE ); if (va_status != VA_STATUS_SUCCESS) return va_status; /* Render subpictures to the output surface, applying scaling */ va_status = render_subpictures( driver_data, obj_surface, obj_glx_surface->gl_output, &src_rect, &dst_rect ); if (va_status != VA_STATUS_SUCCESS) return va_status; } /* Render to Pixmap */ else { dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = obj_glx_surface->width; dst_rect.height = obj_glx_surface->height; va_status = put_surface( driver_data, obj_surface->base.id, obj_glx_surface->pixo->pixmap, obj_glx_surface->width, obj_glx_surface->height, &src_rect, &dst_rect, flags | VA_CLEAR_DRAWABLE ); if (va_status != VA_STATUS_SUCCESS) return va_status; /* Force rendering of fields now */ if ((flags ^ (VA_TOP_FIELD|VA_BOTTOM_FIELD)) != 0) { object_output_p obj_output; obj_output = output_surface_lookup( obj_surface, obj_glx_surface->pixo->pixmap ); ASSERT(obj_output); if (obj_output && obj_output->fields) { va_status = queue_surface(driver_data, obj_surface, obj_output); if (va_status != VA_STATUS_SUCCESS) return va_status; } } } obj_glx_surface->va_surface = obj_surface->base.id; return VA_STATUS_SUCCESS; } VAStatus vdpau_AssociateSurfaceGLX( VADriverContextP ctx, void *gl_surface, VASurfaceID surface, unsigned int flags ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; object_surface_p obj_surface = VDPAU_SURFACE(surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs; if (!gl_set_current_context(obj_glx_surface->gl_context, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; VAStatus va_status; va_status = associate_glx_surface( driver_data, obj_glx_surface, obj_surface, flags ); gl_set_current_context(&old_cs, NULL); return va_status; } // vaDeassociateSurfaceGLX static VAStatus deassociate_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface ) { if (!vdpau_gl_interop()) { if (!gl_unbind_pixmap_object(obj_glx_surface->pixo)) return VA_STATUS_ERROR_OPERATION_FAILED; } obj_glx_surface->va_surface = VA_INVALID_SURFACE; return VA_STATUS_SUCCESS; } VAStatus vdpau_DeassociateSurfaceGLX( VADriverContextP ctx, void *gl_surface ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs; if (!gl_set_current_context(obj_glx_surface->gl_context, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; VAStatus va_status; va_status = deassociate_glx_surface(driver_data, obj_glx_surface); gl_set_current_context(&old_cs, NULL); return va_status; } // vaSyncSurfaceGLX static inline VAStatus sync_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface ) { object_surface_p obj_surface = VDPAU_SURFACE(obj_glx_surface->va_surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; return sync_surface(driver_data, obj_surface); } VAStatus vdpau_SyncSurfaceGLX( VADriverContextP ctx, void *gl_surface ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs; if (!gl_set_current_context(obj_glx_surface->gl_context, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; VAStatus va_status; va_status = sync_glx_surface(driver_data, obj_glx_surface); gl_set_current_context(&old_cs, NULL); return va_status; } // vaBeginRenderSurfaceGLX static inline VAStatus begin_render_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface ) { VAStatus va_status = sync_glx_surface(driver_data, obj_glx_surface); if (va_status != VA_STATUS_SUCCESS) return va_status; if (vdpau_gl_interop()) { if (!gl_vdpau_bind_surface(obj_glx_surface->gl_surface)) return VA_STATUS_ERROR_OPERATION_FAILED; } else { if (!gl_bind_pixmap_object(obj_glx_surface->pixo)) return VA_STATUS_ERROR_OPERATION_FAILED; } return VA_STATUS_SUCCESS; } VAStatus vdpau_BeginRenderSurfaceGLX( VADriverContextP ctx, void *gl_surface ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs; if (!gl_set_current_context(obj_glx_surface->gl_context, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; VAStatus va_status; va_status = begin_render_glx_surface(driver_data, obj_glx_surface); gl_set_current_context(&old_cs, NULL); return va_status; } // vaEndRenderSurfaceGLX static inline VAStatus end_render_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface ) { if (vdpau_gl_interop()) { if (!gl_vdpau_unbind_surface(obj_glx_surface->gl_surface)) return VA_STATUS_ERROR_OPERATION_FAILED; } else { if (!gl_unbind_pixmap_object(obj_glx_surface->pixo)) return VA_STATUS_ERROR_OPERATION_FAILED; } return VA_STATUS_SUCCESS; } VAStatus vdpau_EndRenderSurfaceGLX( VADriverContextP ctx, void *gl_surface ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs; if (!gl_set_current_context(obj_glx_surface->gl_context, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; VAStatus va_status; va_status = end_render_glx_surface(driver_data, obj_glx_surface); gl_set_current_context(&old_cs, NULL); return va_status; } // vaCopySurfaceGLX static VAStatus copy_glx_surface( vdpau_driver_data_t *driver_data, object_glx_surface_p obj_glx_surface, object_surface_p obj_surface, unsigned int flags ) { /* Create framebuffer surface */ if (!obj_glx_surface->fbo) { obj_glx_surface->fbo = gl_create_framebuffer_object( obj_glx_surface->target, obj_glx_surface->texture, obj_glx_surface->width, obj_glx_surface->height ); if (!obj_glx_surface->fbo) return VA_STATUS_ERROR_ALLOCATION_FAILED; } ASSERT(obj_glx_surface->fbo); /* Associate VA surface */ VAStatus va_status; va_status = associate_glx_surface( driver_data, obj_glx_surface, obj_surface, flags ); if (va_status != VA_STATUS_SUCCESS) return va_status; /* Render to FBO */ gl_bind_framebuffer_object(obj_glx_surface->fbo); va_status = begin_render_glx_surface(driver_data, obj_glx_surface); if (va_status == VA_STATUS_SUCCESS) { render_pixmap(driver_data, obj_glx_surface); va_status = end_render_glx_surface(driver_data, obj_glx_surface); } gl_unbind_framebuffer_object(obj_glx_surface->fbo); if (va_status != VA_STATUS_SUCCESS) return va_status; va_status = deassociate_glx_surface(driver_data, obj_glx_surface); if (va_status != VA_STATUS_SUCCESS) return va_status; return VA_STATUS_SUCCESS; } VAStatus vdpau_CopySurfaceGLX( VADriverContextP ctx, void *gl_surface, VASurfaceID surface, unsigned int flags ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_GLX); /* Make sure we have the necessary GLX extensions */ if (!ensure_extensions()) return VA_STATUS_ERROR_OPERATION_FAILED; object_glx_surface_p obj_glx_surface = gl_surface; if (!obj_glx_surface) return VA_STATUS_ERROR_INVALID_SURFACE; object_surface_p obj_surface = VDPAU_SURFACE(surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; GLContextState old_cs; if (!gl_set_current_context(obj_glx_surface->gl_context, &old_cs)) return VA_STATUS_ERROR_OPERATION_FAILED; VAStatus va_status; va_status = copy_glx_surface( driver_data, obj_glx_surface, obj_surface, flags ); gl_set_current_context(&old_cs, NULL); return va_status; } vdpau-driver-0.7.4/src/vdpau_video_glx.h000066400000000000000000000055121203356434100202550ustar00rootroot00000000000000/* * vdpau_video_glx.h - VDPAU backend for VA-API (GLX rendering) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_VIDEO_GLX_H #define VDPAU_VIDEO_GLX_H #include "vdpau_driver.h" #include "vdpau_video_x11.h" #include "utils_glx.h" typedef struct object_glx_surface object_glx_surface_t; typedef struct object_glx_surface *object_glx_surface_p; struct object_glx_surface { struct object_base base; GLContextState *gl_context; GLVdpSurface *gl_surface; object_output_p gl_output; GLenum target; GLuint texture; VASurfaceID va_surface; unsigned int width; unsigned int height; GLPixmapObject *pixo; GLFramebufferObject *fbo; }; // vaCreateSurfaceGLX VAStatus vdpau_CreateSurfaceGLX( VADriverContextP ctx, unsigned int target, unsigned int texture, void **gl_surface ) attribute_hidden; // vaDestroySurfaceGLX VAStatus vdpau_DestroySurfaceGLX( VADriverContextP ctx, void *gl_surface ) attribute_hidden; // vaAssociateSurfaceGLX VAStatus vdpau_AssociateSurfaceGLX( VADriverContextP ctx, void *gl_surface, VASurfaceID surface, unsigned int flags ) attribute_hidden; // vaDeassociateSurfaceGLX VAStatus vdpau_DeassociateSurfaceGLX( VADriverContextP ctx, void *gl_surface ) attribute_hidden; // vaSyncSurfaceGLX VAStatus vdpau_SyncSurfaceGLX( VADriverContextP ctx, void *gl_surface ) attribute_hidden; // vaBeginRenderSurfaceGLX VAStatus vdpau_BeginRenderSurfaceGLX( VADriverContextP ctx, void *gl_surface ) attribute_hidden; // vaEndRenderSurfaceGLX VAStatus vdpau_EndRenderSurfaceGLX( VADriverContextP ctx, void *gl_surface ) attribute_hidden; // vaCopySurfaceGLX VAStatus vdpau_CopySurfaceGLX( VADriverContextP ctx, void *gl_surface, VASurfaceID surface, unsigned int flags ) attribute_hidden; #endif /* VDPAU_VIDEO_GLX_H */ vdpau-driver-0.7.4/src/vdpau_video_x11.c000066400000000000000000000620301203356434100200650ustar00rootroot00000000000000/* * vdpau_video.h - VDPAU backend for VA-API (X11 rendering) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "sysdeps.h" #include "vdpau_video.h" #include "vdpau_video_x11.h" #include "vdpau_subpic.h" #include "vdpau_mixer.h" #include "utils.h" #include "utils_x11.h" #define DEBUG 1 #include "debug.h" // Checks whether drawable is a window static int is_window(Display *dpy, Drawable drawable) { XWindowAttributes wattr; x11_trap_errors(); XGetWindowAttributes(dpy, drawable, &wattr); return x11_untrap_errors() == 0; } // Checks whether a ConfigureNotify event is in the queue typedef struct { Window window; unsigned int width; unsigned int height; unsigned int match; } ConfigureNotifyEventPendingArgs; static Bool configure_notify_event_pending_cb(Display *dpy, XEvent *xev, XPointer arg) { ConfigureNotifyEventPendingArgs * const args = (ConfigureNotifyEventPendingArgs *)arg; if (xev->type == ConfigureNotify && xev->xconfigure.window == args->window && xev->xconfigure.width == args->width && xev->xconfigure.height == args->height) args->match = 1; /* XXX: this is a hack to traverse the whole queue because we can't use XPeekIfEvent() since it could block */ return False; } static int configure_notify_event_pending( vdpau_driver_data_t *driver_data, object_output_p obj_output, unsigned int width, unsigned int height ) { if (!obj_output->is_window) return 0; XEvent xev; ConfigureNotifyEventPendingArgs args; args.window = obj_output->drawable; args.width = width; args.height = height; args.match = 0; /* XXX: don't use XPeekIfEvent() because it might block */ XCheckIfEvent( driver_data->x11_dpy, &xev, configure_notify_event_pending_cb, (XPointer)&args ); return args.match; } // Locks output surfaces static inline void output_surface_lock(object_output_p obj_output) { } // Unlocks output surfaces static inline void output_surface_unlock(object_output_p obj_output) { } // Ensure output surface size matches drawable size int output_surface_ensure_size( vdpau_driver_data_t *driver_data, object_output_p obj_output, unsigned int width, unsigned int height ) { unsigned int i; if (!obj_output) return -1; if (width > obj_output->max_width || height > obj_output->max_height) { const unsigned int max_waste = 1U << 8; obj_output->max_width = (width + max_waste - 1) & -max_waste; obj_output->max_height = (height + max_waste - 1) & -max_waste; for (i = 0; i < VDPAU_MAX_OUTPUT_SURFACES; i++) { if (obj_output->vdp_output_surfaces[i] != VDP_INVALID_HANDLE) { vdpau_output_surface_destroy( driver_data, obj_output->vdp_output_surfaces[i] ); obj_output->vdp_output_surfaces[i] = VDP_INVALID_HANDLE; obj_output->vdp_output_surfaces_dirty[i] = 0; } } } obj_output->size_changed = ( (obj_output->width != width || obj_output->height != height) && !configure_notify_event_pending(driver_data, obj_output, width, height) ); if (obj_output->size_changed) { obj_output->width = width; obj_output->height = height; for (i = 0; i < VDPAU_MAX_OUTPUT_SURFACES; i++) obj_output->vdp_output_surfaces_dirty[i] = 0; } if (obj_output->vdp_output_surfaces[obj_output->current_output_surface] == VDP_INVALID_HANDLE) { VdpStatus vdp_status; vdp_status = vdpau_output_surface_create( driver_data, driver_data->vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, obj_output->max_width, obj_output->max_height, &obj_output->vdp_output_surfaces[obj_output->current_output_surface] ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpOutputSurfaceCreate()")) return -1; } return 0; } // Create output surface object_output_p output_surface_create( vdpau_driver_data_t *driver_data, Drawable drawable, unsigned int width, unsigned int height ) { VASurfaceID surface = object_heap_allocate(&driver_data->output_heap); if (surface == VA_INVALID_ID) return NULL; object_output_p obj_output = VDPAU_OUTPUT(surface); if (!obj_output) return NULL; obj_output->refcount = 1; obj_output->drawable = drawable; obj_output->width = width; obj_output->height = height; obj_output->max_width = 0; obj_output->max_height = 0; obj_output->vdp_flip_queue = VDP_INVALID_HANDLE; obj_output->vdp_flip_target = VDP_INVALID_HANDLE; obj_output->current_output_surface = 0; obj_output->displayed_output_surface = 0; obj_output->queued_surfaces = 0; obj_output->fields = 0; obj_output->is_window = 0; obj_output->size_changed = 0; if (drawable != None) obj_output->is_window = is_window(driver_data->x11_dpy, drawable); unsigned int i; for (i = 0; i < VDPAU_MAX_OUTPUT_SURFACES; i++) { obj_output->vdp_output_surfaces[i] = VDP_INVALID_HANDLE; obj_output->vdp_output_surfaces_dirty[i] = 0; } pthread_mutex_init(&obj_output->vdp_output_surfaces_lock, NULL); if (drawable != None) { VdpStatus vdp_status; vdp_status = vdpau_presentation_queue_target_create_x11( driver_data, driver_data->vdp_device, obj_output->drawable, &obj_output->vdp_flip_target ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpPresentationQueueTargetCreateX115)")) { output_surface_destroy(driver_data, obj_output); return NULL; } vdp_status = vdpau_presentation_queue_create( driver_data, driver_data->vdp_device, obj_output->vdp_flip_target, &obj_output->vdp_flip_queue ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpPresentationQueueCreate()")) { output_surface_destroy(driver_data, obj_output); return NULL; } } return obj_output; } // Destroy output surface void output_surface_destroy( vdpau_driver_data_t *driver_data, object_output_p obj_output ) { if (!obj_output) return; if (obj_output->vdp_flip_queue != VDP_INVALID_HANDLE) { vdpau_presentation_queue_destroy( driver_data, obj_output->vdp_flip_queue ); obj_output->vdp_flip_queue = VDP_INVALID_HANDLE; } if (obj_output->vdp_flip_target != VDP_INVALID_HANDLE) { vdpau_presentation_queue_target_destroy( driver_data, obj_output->vdp_flip_target ); obj_output->vdp_flip_target = VDP_INVALID_HANDLE; } unsigned int i; for (i = 0; i < VDPAU_MAX_OUTPUT_SURFACES; i++) { VdpOutputSurface vdp_output_surface; vdp_output_surface = obj_output->vdp_output_surfaces[i]; if (vdp_output_surface != VDP_INVALID_HANDLE) { vdpau_output_surface_destroy(driver_data, vdp_output_surface); obj_output->vdp_output_surfaces[i] = VDP_INVALID_HANDLE; } } pthread_mutex_unlock(&obj_output->vdp_output_surfaces_lock); pthread_mutex_destroy(&obj_output->vdp_output_surfaces_lock); object_heap_free(&driver_data->output_heap, (object_base_p)obj_output); } // Reference output surface object_output_p output_surface_ref( vdpau_driver_data_t *driver_data, object_output_p obj_output ) { if (!obj_output) return NULL; output_surface_lock(obj_output); ++obj_output->refcount; output_surface_unlock(obj_output); return obj_output; } // Unreference output surface, destroying the surface if refcount reaches zero void output_surface_unref( vdpau_driver_data_t *driver_data, object_output_p obj_output ) { if (!obj_output) return; output_surface_lock(obj_output); --obj_output->refcount; output_surface_unlock(obj_output); if (obj_output->refcount == 0) output_surface_destroy(driver_data, obj_output); } // Looks up output surface object_output_p output_surface_lookup(object_surface_p obj_surface, Drawable drawable) { unsigned int i; if (obj_surface) { for (i = 0; i < obj_surface->output_surfaces_count; i++) { ASSERT(obj_surface->output_surfaces[i]); if (obj_surface->output_surfaces[i]->drawable == drawable) return obj_surface->output_surfaces[i]; } } return NULL; } // Ensure an output surface is created for the specified surface and drawable static object_output_p output_surface_ensure( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, Drawable drawable, unsigned int width, unsigned int height ) { object_output_p obj_output = NULL; int new_obj_output = 0; if (!obj_surface) return NULL; /* Check for a output surface matching Drawable */ obj_output = output_surface_lookup(obj_surface, drawable); /* ... that might have been created for another video surface */ if (!obj_output) { object_heap_iterator iter; object_base_p obj = object_heap_first(&driver_data->output_heap, &iter); while (obj) { object_output_p m = (object_output_p)obj; if (m->drawable == drawable) { obj_output = output_surface_ref(driver_data, m); new_obj_output = 1; break; } obj = object_heap_next(&driver_data->output_heap, &iter); } } /* Fallback: create a new output surface */ if (!obj_output) { obj_output = output_surface_create(driver_data, drawable, width, height); if (!obj_output) return NULL; new_obj_output = 1; } /* Append output surface */ if (new_obj_output) { if (realloc_buffer((void **)&obj_surface->output_surfaces, &obj_surface->output_surfaces_count_max, 1 + obj_surface->output_surfaces_count, sizeof(*obj_surface->output_surfaces)) == NULL) return NULL; obj_surface->output_surfaces[obj_surface->output_surfaces_count++] = obj_output; } return obj_output; } // Ensure rectangle is within specified bounds static inline void ensure_bounds(VdpRect *rect, unsigned int width, unsigned int height) { rect->x0 = MAX(rect->x0, 0); rect->y0 = MAX(rect->y0, 0); rect->x1 = MIN(rect->x1, width); rect->y1 = MIN(rect->y1, height); } // Render surface to the VDPAU output surface VAStatus render_surface( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output, const VARectangle *source_rect, const VARectangle *target_rect, unsigned int flags ) { VdpRect src_rect; src_rect.x0 = source_rect->x; src_rect.y0 = source_rect->y; src_rect.x1 = source_rect->x + source_rect->width; src_rect.y1 = source_rect->y + source_rect->height; ensure_bounds(&src_rect, obj_surface->width, obj_surface->height); VdpRect dst_rect; dst_rect.x0 = target_rect->x; dst_rect.y0 = target_rect->y; dst_rect.x1 = target_rect->x + target_rect->width; dst_rect.y1 = target_rect->y + target_rect->height; ensure_bounds(&dst_rect, obj_output->width, obj_output->height); VdpOutputSurface vdp_background = VDP_INVALID_HANDLE; if (!obj_output->size_changed && obj_output->queued_surfaces > 0) { int background_surface; background_surface = obj_output->displayed_output_surface; if (obj_output->vdp_output_surfaces_dirty[background_surface]) vdp_background = obj_output->vdp_output_surfaces[background_surface]; } VdpStatus vdp_status; vdp_status = video_mixer_render( driver_data, obj_surface->video_mixer, obj_surface, vdp_background, obj_output->vdp_output_surfaces[obj_output->current_output_surface], &src_rect, &dst_rect, flags ); obj_output->vdp_output_surfaces_dirty[obj_output->current_output_surface] = 1; return vdpau_get_VAStatus(vdp_status); } // Render subpictures to the VDPAU output surface static VAStatus render_subpicture( vdpau_driver_data_t *driver_data, object_subpicture_p obj_subpicture, object_surface_p obj_surface, object_output_p obj_output, const VARectangle *source_rect, const VARectangle *target_rect, const SubpictureAssociationP assoc ) { VAStatus va_status = commit_subpicture(driver_data, obj_subpicture); if (va_status != VA_STATUS_SUCCESS) return va_status; object_image_p obj_image = VDPAU_IMAGE(obj_subpicture->image_id); if (!obj_image) return VA_STATUS_ERROR_INVALID_IMAGE; VARectangle * const sp_src_rect = &assoc->src_rect; VARectangle * const sp_dst_rect = &assoc->dst_rect; VdpRect clip_rect; clip_rect.x0 = MAX(sp_dst_rect->x, source_rect->x); clip_rect.y0 = MAX(sp_dst_rect->y, source_rect->y); clip_rect.x1 = MIN(sp_dst_rect->x + sp_dst_rect->width, source_rect->x + source_rect->width); clip_rect.y1 = MIN(sp_dst_rect->y + sp_dst_rect->height, source_rect->y + source_rect->height); /* Check we actually have something to render */ if (clip_rect.x1 <= clip_rect.x0 || clip_rect.y1 < clip_rect.y0) return VA_STATUS_SUCCESS; /* Recompute clipped source area (relative to subpicture) */ VdpRect src_rect; { const float sx = sp_src_rect->width / (float)sp_dst_rect->width; const float sy = sp_src_rect->height / (float)sp_dst_rect->height; src_rect.x0 = sp_src_rect->x + (clip_rect.x0 - sp_dst_rect->x) * sx; src_rect.x1 = sp_src_rect->x + (clip_rect.x1 - sp_dst_rect->x) * sx; src_rect.y0 = sp_src_rect->y + (clip_rect.y0 - sp_dst_rect->y) * sy; src_rect.y1 = sp_src_rect->y + (clip_rect.y1 - sp_dst_rect->y) * sy; ensure_bounds(&src_rect, obj_subpicture->width, obj_subpicture->height); } /* Recompute clipped target area (relative to output surface) */ VdpRect dst_rect; { const float sx = target_rect->width / (float)source_rect->width; const float sy = target_rect->height / (float)source_rect->height; dst_rect.x0 = target_rect->x + clip_rect.x0 * sx; dst_rect.x1 = target_rect->x + clip_rect.x1 * sx; dst_rect.y0 = target_rect->y + clip_rect.y0 * sy; dst_rect.y1 = target_rect->y + clip_rect.y1 * sy; ensure_bounds(&dst_rect, obj_output->width, obj_output->height); } VdpOutputSurfaceRenderBlendState blend_state; blend_state.struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION; blend_state.blend_factor_source_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA; blend_state.blend_factor_source_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA; blend_state.blend_factor_destination_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; blend_state.blend_factor_destination_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; blend_state.blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD; blend_state.blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD; VdpStatus vdp_status; VdpColor color = { 1.0, 1.0, 1.0, obj_subpicture->alpha }; switch (obj_image->vdp_format_type) { case VDP_IMAGE_FORMAT_TYPE_RGBA: vdp_status = vdpau_output_surface_render_bitmap_surface( driver_data, obj_output->vdp_output_surfaces[obj_output->current_output_surface], &dst_rect, obj_subpicture->vdp_bitmap_surface, &src_rect, &color, &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0 ); break; case VDP_IMAGE_FORMAT_TYPE_INDEXED: vdp_status = vdpau_output_surface_render_output_surface( driver_data, obj_output->vdp_output_surfaces[obj_output->current_output_surface], &dst_rect, obj_subpicture->vdp_output_surface, &src_rect, NULL, &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0 ); break; default: vdp_status = VDP_STATUS_ERROR; break; } return vdpau_get_VAStatus(vdp_status); } VAStatus render_subpictures( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output, const VARectangle *source_rect, const VARectangle *target_rect ) { unsigned int i; for (i = 0; i < obj_surface->assocs_count; i++) { SubpictureAssociationP const assoc = obj_surface->assocs[i]; ASSERT(assoc); if (!assoc) continue; object_subpicture_p obj_subpicture; obj_subpicture = VDPAU_SUBPICTURE(assoc->subpicture); ASSERT(obj_subpicture); if (!obj_subpicture) continue; VAStatus va_status = render_subpicture( driver_data, obj_subpicture, obj_surface, obj_output, source_rect, target_rect, assoc ); if (va_status != VA_STATUS_SUCCESS) return va_status; } return VA_STATUS_SUCCESS; } // Queue surface for display static VAStatus flip_surface_unlocked( vdpau_driver_data_t *driver_data, object_output_p obj_output ) { VdpStatus vdp_status; vdp_status = vdpau_presentation_queue_display( driver_data, obj_output->vdp_flip_queue, obj_output->vdp_output_surfaces[obj_output->current_output_surface], obj_output->width, obj_output->height, 0 ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpPresentationQueueDisplay()")) return vdpau_get_VAStatus(vdp_status); obj_output->displayed_output_surface = obj_output->current_output_surface; obj_output->current_output_surface = (++obj_output->queued_surfaces) % VDPAU_MAX_OUTPUT_SURFACES; return VA_STATUS_SUCCESS; } static VAStatus queue_surface_unlocked( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output ) { obj_surface->va_surface_status = VASurfaceDisplaying; obj_output->fields = 0; return flip_surface_unlocked(driver_data, obj_output); } VAStatus queue_surface( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output ) { VAStatus va_status; output_surface_lock(obj_output); va_status = queue_surface_unlocked(driver_data, obj_surface, obj_output); output_surface_unlock(obj_output); return va_status; } // Render surface to a Drawable static VAStatus put_surface_unlocked( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output, const VARectangle *source_rect, const VARectangle *target_rect, unsigned int flags ) { VdpStatus vdp_status; VAStatus va_status; obj_surface->va_surface_status = VASurfaceReady; /* Wait for the output surface to be ready. i.e. it completed the previous rendering */ if (obj_output->vdp_output_surfaces[obj_output->current_output_surface] != VDP_INVALID_HANDLE && obj_output->vdp_output_surfaces_dirty[obj_output->current_output_surface]) { VdpTime dummy_time; vdp_status = vdpau_presentation_queue_block_until_surface_idle( driver_data, obj_output->vdp_flip_queue, obj_output->vdp_output_surfaces[obj_output->current_output_surface], &dummy_time ); if (!VDPAU_CHECK_STATUS(vdp_status, "VdpPresentationQueueBlockUntilSurfaceIdle()")) return vdpau_get_VAStatus(vdp_status); } /* Render the video surface to the output surface */ va_status = render_surface( driver_data, obj_surface, obj_output, source_rect, target_rect, flags ); if (va_status != VA_STATUS_SUCCESS) return va_status; /* Render subpictures to the output surface, applying scaling */ va_status = render_subpictures( driver_data, obj_surface, obj_output, source_rect, target_rect ); if (va_status != VA_STATUS_SUCCESS) return va_status; /* Queue surface for display, if the picture is complete (all fields mixed in) */ int fields = flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD); if (!fields) fields = VA_TOP_FIELD|VA_BOTTOM_FIELD; obj_output->fields |= fields; if (obj_output->fields == (VA_TOP_FIELD|VA_BOTTOM_FIELD)) { va_status = queue_surface_unlocked(driver_data, obj_surface, obj_output); if (va_status != VA_STATUS_SUCCESS) return va_status; } return VA_STATUS_SUCCESS; } VAStatus put_surface( vdpau_driver_data_t *driver_data, VASurfaceID surface, Drawable drawable, unsigned int drawable_width, unsigned int drawable_height, const VARectangle *source_rect, const VARectangle *target_rect, unsigned int flags ) { VAStatus va_status; int status; object_surface_p obj_surface = VDPAU_SURFACE(surface); if (!obj_surface) return VA_STATUS_ERROR_INVALID_SURFACE; object_output_p obj_output; obj_output = output_surface_ensure( driver_data, obj_surface, drawable, drawable_width, drawable_height ); if (!obj_output) return VA_STATUS_ERROR_INVALID_SURFACE; ASSERT(obj_output->drawable == drawable); ASSERT(obj_output->vdp_flip_queue != VDP_INVALID_HANDLE); ASSERT(obj_output->vdp_flip_target != VDP_INVALID_HANDLE); int fields = flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD); if (!fields) fields = VA_TOP_FIELD|VA_BOTTOM_FIELD; /* If we are trying to put the same field, this means we have started a new picture, so flush the current one */ if (obj_output->fields & fields) { va_status = queue_surface(driver_data, obj_surface, obj_output); if (va_status != VA_STATUS_SUCCESS) return va_status; } /* Resize output surface */ output_surface_lock(obj_output); status = output_surface_ensure_size( driver_data, obj_output, drawable_width, drawable_height ); output_surface_unlock(obj_output); if (status < 0) return VA_STATUS_ERROR_OPERATION_FAILED; output_surface_lock(obj_output); va_status = put_surface_unlocked( driver_data, obj_surface, obj_output, source_rect, target_rect, flags ); output_surface_unlock(obj_output); return va_status; } // vaPutSurface VAStatus vdpau_PutSurface( VADriverContextP ctx, VASurfaceID surface, VADrawable draw, short srcx, short srcy, unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, unsigned short desth, VARectangle *cliprects, unsigned int number_cliprects, unsigned int flags ) { VDPAU_DRIVER_DATA_INIT; vdpau_set_display_type(driver_data, VA_DISPLAY_X11); /* XXX: no clip rects supported */ if (cliprects || number_cliprects > 0) return VA_STATUS_ERROR_INVALID_PARAMETER; unsigned int w, h; const XID xid = (XID)(uintptr_t)draw; if (x11_get_geometry(driver_data->x11_dpy, xid, NULL, NULL, &w, &h) < 0) return VA_STATUS_ERROR_OPERATION_FAILED; VARectangle src_rect, dst_rect; src_rect.x = srcx; src_rect.y = srcy; src_rect.width = srcw; src_rect.height = srch; dst_rect.x = destx; dst_rect.y = desty; dst_rect.width = destw; dst_rect.height = desth; return put_surface(driver_data, surface, xid, w, h, &src_rect, &dst_rect, flags); } vdpau-driver-0.7.4/src/vdpau_video_x11.h000066400000000000000000000114511203356434100200730ustar00rootroot00000000000000/* * vdpau_video_x11.h - VDPAU backend for VA-API (X11 rendering) * * libva-vdpau-driver (C) 2009-2011 Splitted-Desktop Systems * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef VDPAU_VIDEO_X11_H #define VDPAU_VIDEO_X11_H #include "vdpau_driver.h" #include #include "uasyncqueue.h" typedef struct object_output object_output_t; struct object_output { struct object_base base; unsigned int refcount; Drawable drawable; unsigned int width; unsigned int height; unsigned int max_width; unsigned int max_height; VdpPresentationQueue vdp_flip_queue; VdpPresentationQueueTarget vdp_flip_target; VdpOutputSurface vdp_output_surfaces[VDPAU_MAX_OUTPUT_SURFACES]; unsigned int vdp_output_surfaces_dirty[VDPAU_MAX_OUTPUT_SURFACES]; pthread_mutex_t vdp_output_surfaces_lock; unsigned int current_output_surface; unsigned int displayed_output_surface; unsigned int queued_surfaces; unsigned int fields; unsigned int is_window : 1; /* drawable is a window */ unsigned int size_changed : 1; /* size changed since previous vaPutSurface() and user noticed the change */ }; // Create output surface object_output_p output_surface_create( vdpau_driver_data_t *driver_data, Drawable drawable, unsigned int width, unsigned int height ) attribute_hidden; // Destroy output surface void output_surface_destroy( vdpau_driver_data_t *driver_data, object_output_p obj_output ) attribute_hidden; // Reference output surface object_output_p output_surface_ref( vdpau_driver_data_t *driver_data, object_output_p obj_output ) attribute_hidden; // Unreference output surface // NOTE: this destroys the surface if refcount reaches zero void output_surface_unref( vdpau_driver_data_t *driver_data, object_output_p obj_output ) attribute_hidden; // Looks up output surface object_output_p output_surface_lookup(object_surface_p obj_surface, Drawable drawable) attribute_hidden; // Ensure output surface size matches drawable size int output_surface_ensure_size( vdpau_driver_data_t *driver_data, object_output_p obj_output, unsigned int width, unsigned int height ) attribute_hidden; // Render surface to the VDPAU output surface VAStatus render_surface( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output, const VARectangle *source_rect, const VARectangle *target_rect, unsigned int flags ) attribute_hidden; // Render subpictures to the VDPAU output surface VAStatus render_subpictures( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output, const VARectangle *source_rect, const VARectangle *target_rect ) attribute_hidden; // Render surface to a Drawable VAStatus put_surface( vdpau_driver_data_t *driver_data, VASurfaceID surface, Drawable drawable, unsigned int drawable_width, unsigned int drawable_height, const VARectangle *source_rect, const VARectangle *target_rect, unsigned int flags ) attribute_hidden; // Queue surface for display VAStatus queue_surface( vdpau_driver_data_t *driver_data, object_surface_p obj_surface, object_output_p obj_output ) attribute_hidden; // vaPutSurface VAStatus vdpau_PutSurface( VADriverContextP ctx, VASurfaceID surface, VADrawable draw, short srcx, short srcy, unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, unsigned short desth, VARectangle *cliprects, unsigned int number_cliprects, unsigned int flags ) attribute_hidden; #endif /* VDPAU_VIDEO_X11_H */